mirror of
https://github.com/anope/anope.git
synced 2026-06-17 06:24:46 +02:00
Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ae4a022eb | |||
| ea8a692191 | |||
| 026d6c461d | |||
| 3cbac4bcea | |||
| e42b4c21b7 | |||
| 2464913200 | |||
| ebea728957 | |||
| 233a5bf4cd | |||
| 7019b27e59 | |||
| 70227dc882 | |||
| 6178ea644a | |||
| df7f0730dd | |||
| 331168379f | |||
| 5220963be1 | |||
| 436dab3eb8 | |||
| c3055e1cfa | |||
| a27be92e4b | |||
| faf0ad5f35 | |||
| e9202916b2 | |||
| 2cb20ded78 | |||
| 687bcaa83f | |||
| 1fb8a624f9 | |||
| b4b51d4828 | |||
| 7083c424c2 | |||
| c55d8450a4 | |||
| 7a20f26b84 | |||
| de16238e01 | |||
| 240f8b9e50 | |||
| 656ca80dd0 | |||
| d40cbdb8cf | |||
| a668c8b520 | |||
| bc44195a3d | |||
| a7cbe2a139 | |||
| 8408bf95c7 | |||
| 309c342b86 | |||
| 4de59d61d8 | |||
| 0dc65cc162 | |||
| 2e6c90d502 | |||
| 127ea3e68a | |||
| ba11b5eab0 | |||
| df1c6176b3 | |||
| 96ccfe4cbe | |||
| 8634594cd1 | |||
| ee160842b3 | |||
| 613452acba | |||
| 9411dac991 | |||
| aa32f7c926 | |||
| 517810b208 | |||
| b7f7a91dfb | |||
| b6e4c7302e | |||
| b7590e20c1 | |||
| 4952a9c852 | |||
| 59647baff9 | |||
| 1393518555 | |||
| 51827b94ad | |||
| 98c840eb02 | |||
| 24cbb84009 |
@@ -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
|
||||
@@ -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`:**
|
||||
|
||||
@@ -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
|
||||
@@ -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**
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -14,3 +14,4 @@ modules/ssl_openssl.cpp
|
||||
modules/stats
|
||||
run/
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
@@ -1149,9 +1149,10 @@ module
|
||||
|
||||
/* Whether or not to import data from another database module in to SQL on startup.
|
||||
* If you enable this, be sure that the database services is configured to use is
|
||||
* empty and that another database module to import from is loaded before db_sql.
|
||||
* After you enable this and do a database import you should disable it for
|
||||
* subsequent restarts.
|
||||
* empty and that another database module to import from is loaded BEFORE db_sql.
|
||||
* After you enable this and do a database import you MUST disable it for
|
||||
* subsequent restarts. If you want to keep writing a flatfile database after the
|
||||
* SQL import is done you should load db_flatfile AFTER this module.
|
||||
*
|
||||
* Note that you can not import databases using db_sql_live. If you want to import
|
||||
* databases and use db_sql_live you should import them using db_sql, then shut down
|
||||
|
||||
@@ -737,7 +737,7 @@ privilege
|
||||
privilege
|
||||
{
|
||||
name = "SET"
|
||||
desc = _("Allowed to set channel settings")
|
||||
desc = _("Allowed to modify channel settings")
|
||||
rank = 320
|
||||
level = 9999
|
||||
flag = "s"
|
||||
@@ -1256,7 +1256,7 @@ 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 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"); }
|
||||
|
||||
/*
|
||||
|
||||
+33
-21
@@ -203,13 +203,17 @@ module
|
||||
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.
|
||||
*
|
||||
* This directive is optional. If not set it defaults to "Guest"
|
||||
* 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####"
|
||||
*/
|
||||
guestnickprefix = "Guest"
|
||||
guestnick = "Guest####"
|
||||
|
||||
/*
|
||||
* If set, Anope does not allow ownership of nick names, only ownership of accounts.
|
||||
@@ -521,22 +525,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/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"; }
|
||||
@@ -553,9 +546,6 @@ command { service = "NickServ"; name = "SASET EMAIL"; command = "nickserv/saset/
|
||||
command { service = "NickServ"; name = "SET KEEPMODES"; command = "nickserv/set/keepmodes"; }
|
||||
command { service = "NickServ"; name = "SASET KEEPMODES"; command = "nickserv/saset/keepmodes"; permission = "nickserv/saset/keepmodes"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/kill"; }
|
||||
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/kill"; permission = "nickserv/saset/kill"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET PASSWORD"; command = "nickserv/set/password"; }
|
||||
command { service = "NickServ"; name = "SASET PASSWORD"; command = "nickserv/saset/password"; permission = "nickserv/saset/password"; }
|
||||
|
||||
@@ -564,6 +554,28 @@ command { service = "NickServ"; name = "SASET NEVEROP"; command = "nickserv/sase
|
||||
|
||||
command { service = "NickServ"; name = "SASET NOEXPIRE"; command = "nickserv/saset/noexpire"; permission = "nickserv/saset/noexpire"; }
|
||||
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
@@ -578,7 +590,7 @@ command { service = "NickServ"; name = "SASET LANGUAGE"; command = "nickserv/sas
|
||||
/*
|
||||
* ns_set_message
|
||||
*
|
||||
* Provides the command nickserv/set/message and nickserv/saset/message.
|
||||
* Provides the commands nickserv/set/message and nickserv/saset/message.
|
||||
*
|
||||
* Allows users to let services send them PRIVMSGs instead of NOTICEs.
|
||||
*
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
Anope Version 2.1.11
|
||||
--------------------
|
||||
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
|
||||
--------------------
|
||||
Added support for NEXTBANS on UnrealIRCd.
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
Anope Version 2.1.11
|
||||
--------------------
|
||||
Moved module:allowkilimmed from the ns_set module to the ns_set_kill module.
|
||||
Moved nickserv/set/kill and nickserv/saset/kill to the ns_set_kill module.
|
||||
Replaced module:guestnickprefix for the nickserv module with module:guestnick.
|
||||
|
||||
Anope Version 2.1.10
|
||||
--------------------
|
||||
Added options:servicealias.
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ 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)
|
||||
|
||||
@@ -473,13 +473,6 @@ namespace Anope
|
||||
*/
|
||||
extern CoreExport bool Encrypt(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]);
|
||||
|
||||
/** Returns a sequence of data formatted as the format argument specifies.
|
||||
** After the format parameter, the function expects at least as many
|
||||
** additional arguments as specified in format.
|
||||
|
||||
@@ -81,6 +81,7 @@ public:
|
||||
bool IsFounder(ChannelInfo *ci);
|
||||
|
||||
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);
|
||||
|
||||
+1
-1
@@ -126,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);
|
||||
|
||||
@@ -194,7 +194,7 @@ public:
|
||||
|
||||
void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override
|
||||
{
|
||||
data.Store(this->name, true);
|
||||
data.Store(this->name, this->HasExt(e));
|
||||
}
|
||||
|
||||
void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
|
||||
|
||||
+36
-1
@@ -55,13 +55,48 @@ 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 */
|
||||
|
||||
@@ -19,4 +19,5 @@ public:
|
||||
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;
|
||||
};
|
||||
|
||||
+1
-3
@@ -98,10 +98,8 @@ public:
|
||||
|
||||
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()
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#define BUFSIZE 1024
|
||||
|
||||
#define _(x) x
|
||||
#define N_(x, y) x, y
|
||||
|
||||
#ifndef _WIN32
|
||||
# define DllExport __attribute__ ((visibility ("default")))
|
||||
|
||||
+4
-4
@@ -164,15 +164,15 @@ public:
|
||||
* @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
|
||||
@@ -503,7 +503,7 @@ public:
|
||||
* @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
|
||||
|
||||
@@ -190,6 +190,7 @@ public:
|
||||
* @param ... any number of parameters
|
||||
*/
|
||||
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;
|
||||
|
||||
|
||||
+1524
-3035
File diff suppressed because it is too large
Load Diff
+485
-600
File diff suppressed because it is too large
Load Diff
+534
-273
File diff suppressed because it is too large
Load Diff
+97
-86
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Anope\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-23 18:32+0100\n"
|
||||
"PO-Revision-Date: 2024-06-23 16:07+0300\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"
|
||||
@@ -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.4.4\n"
|
||||
"X-Generator: Poedit 3.5\n"
|
||||
|
||||
#, c-format
|
||||
msgid "%d channel(s) cleared, and %d channel(s) dropped."
|
||||
@@ -81,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 ""
|
||||
@@ -130,16 +130,16 @@ msgid ""
|
||||
"malicious users from \"taking over\" channels by limiting\n"
|
||||
"who is allowed channel operator privileges. Available\n"
|
||||
"commands are listed below; to use them, type\n"
|
||||
"%s%s command. For more information on a\n"
|
||||
"specific command, type %s%s HELP command.\n"
|
||||
"%s command. For more information on a\n"
|
||||
"specific command, type %s HELP command.\n"
|
||||
msgstr ""
|
||||
"%s 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."
|
||||
@@ -386,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"
|
||||
@@ -457,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
|
||||
@@ -865,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"
|
||||
@@ -946,14 +946,14 @@ msgstr ""
|
||||
#, c-format
|
||||
msgid ""
|
||||
" \n"
|
||||
"See the %s command (%s%s HELP ACCESS) for\n"
|
||||
"See the %s command (%s HELP ACCESS) for\n"
|
||||
"information on giving a subset of these privileges to\n"
|
||||
"other channel users.\n"
|
||||
msgstr ""
|
||||
" \n"
|
||||
"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"
|
||||
@@ -1218,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."
|
||||
@@ -1248,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"
|
||||
|
||||
@@ -1811,6 +1807,9 @@ 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 "Account id"
|
||||
msgstr "Hesap ID"
|
||||
|
||||
msgid "Account registered"
|
||||
msgstr "Hesap kaydedildi"
|
||||
|
||||
@@ -2015,15 +2014,15 @@ 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"
|
||||
|
||||
@@ -2953,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"
|
||||
|
||||
@@ -3668,7 +3675,7 @@ msgstr "%s için e-posta geçersiz."
|
||||
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"
|
||||
@@ -3922,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."
|
||||
@@ -4193,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
|
||||
@@ -4304,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."
|
||||
@@ -4778,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"
|
||||
@@ -4793,7 +4800,7 @@ msgstr ""
|
||||
"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üfür\n"
|
||||
"listesine ekler. SINGLE belirtilirse, yalnızca kullanıcı\n"
|
||||
@@ -5402,8 +5409,8 @@ msgid "Persistent"
|
||||
msgstr "Kalıcı"
|
||||
|
||||
#, c-format
|
||||
msgid "Please confirm that you want to drop %s with %s%s DROP %s %s"
|
||||
msgstr "Lütfen %s rumuzunu droplamak isteğinizi %s%s DROP %s %s ile onaylayın"
|
||||
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."
|
||||
@@ -5899,18 +5906,18 @@ msgstr "OPları koruma %s'de uygulandı."
|
||||
|
||||
#, 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"
|
||||
@@ -6224,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"
|
||||
@@ -6236,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"
|
||||
@@ -6461,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"
|
||||
@@ -6472,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:"
|
||||
@@ -6527,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."
|
||||
@@ -7438,10 +7445,10 @@ msgstr "%zu memo (%s kanalında) var."
|
||||
#, c-format
|
||||
msgid ""
|
||||
"There is a new memo on channel %s.\n"
|
||||
"Type %s%s READ %s %zu to read it."
|
||||
"Type %s READ %s %zu to read it."
|
||||
msgstr ""
|
||||
"%s kanalında yeni bir memo var. Okumak için\n"
|
||||
"%s%s READ %s %zu yazın."
|
||||
"%s READ %s %zu yazın."
|
||||
|
||||
#, c-format
|
||||
msgid "There is no bot assigned to %s anymore."
|
||||
@@ -7738,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"
|
||||
@@ -7906,46 +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 email in order to set your email."
|
||||
msgstr "E-Postanızı ayarlamak için %s%s SET EMAIL e-posta yazın."
|
||||
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"
|
||||
@@ -7993,16 +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%s HELP\" for help."
|
||||
msgstr "Bilinmeyen komut %s. %s mi demek istediniz? Yardım için: \"%s%s HELP\"."
|
||||
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."
|
||||
@@ -8347,10 +8354,6 @@ msgstr "Bir kanalı, onun kendi erişim listesine ekleyemezsiniz."
|
||||
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."
|
||||
@@ -8425,10 +8428,10 @@ msgstr "1 yeni memonuz var."
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You have a new memo from %s.\n"
|
||||
"Type %s%s READ %zu to read it."
|
||||
"Type %s READ %zu to read it."
|
||||
msgstr ""
|
||||
"%s size yeni bir memo gönderdi.\n"
|
||||
"okumak için %s%s READ %zu yazın."
|
||||
"okumak için %s READ %zu yazın."
|
||||
|
||||
#, c-format
|
||||
msgid "You have been invited to %s by %s."
|
||||
@@ -8489,6 +8492,10 @@ 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."
|
||||
|
||||
@@ -8586,6 +8593,10 @@ msgstr "IRCd'niz SVSPART'ı desteklemiyor."
|
||||
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."
|
||||
msgstr "Hesabınız %s başarıyla oluşturuldu."
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
info[_("Real name")] = bi->realname;
|
||||
info[_("Created")] = Anope::strftime(bi->created, source.GetAccount());
|
||||
info[_("Options")] = bi->oper_only ? _("Private") : _("None");
|
||||
info[_("Used on")] = Anope::ToString(bi->GetChannelCount()) + " channel(s)";
|
||||
info[_("Used on")] = Anope::printf(Language::Translate(source.nc, N_("%u channel", "%u channels")), bi->GetChannelCount());
|
||||
|
||||
FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
static Module *me;
|
||||
|
||||
static Anope::map<Anope::string> descriptions;
|
||||
static Anope::map<uint16_t> numerics;
|
||||
|
||||
struct CSMiscData;
|
||||
static Anope::map<ExtensibleItem<CSMiscData> *> items;
|
||||
@@ -189,6 +190,7 @@ public:
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
{
|
||||
descriptions.clear();
|
||||
numerics.clear();
|
||||
|
||||
for (int i = 0; i < conf->CountBlock("command"); ++i)
|
||||
{
|
||||
@@ -204,9 +206,31 @@ public:
|
||||
continue;
|
||||
|
||||
descriptions[cname] = desc;
|
||||
|
||||
auto numeric = block->Get<unsigned>("misc_numeric");
|
||||
if (numeric >= 1 && numeric <= 999)
|
||||
numerics["cs_set_misc:" + GetAttribute(cname)] = numeric;
|
||||
}
|
||||
}
|
||||
|
||||
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 (const auto &[_, e] : items)
|
||||
|
||||
+44
-44
@@ -212,7 +212,7 @@ class MChanstats final
|
||||
|
||||
Anope::string GetDisplay(User *u)
|
||||
{
|
||||
if (u && u->Account() && ns_stats.HasExt(u->Account()))
|
||||
if (u && u->IsIdentified() && ns_stats.HasExt(u->Account()))
|
||||
return u->Account()->display;
|
||||
else
|
||||
return "";
|
||||
@@ -278,45 +278,45 @@ class MChanstats final
|
||||
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` int(10) unsigned NOT NULL DEFAULT '0',"
|
||||
"`words` int(10) 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',"
|
||||
"`letters` bigint unsigned NOT NULL DEFAULT '0',"
|
||||
"`words` bigint 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`),"
|
||||
@@ -332,9 +332,9 @@ class MChanstats final
|
||||
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()));"
|
||||
@@ -368,7 +368,7 @@ class MChanstats final
|
||||
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;"
|
||||
@@ -381,7 +381,7 @@ class MChanstats final
|
||||
"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,"
|
||||
@@ -532,7 +532,7 @@ public:
|
||||
|
||||
void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) override
|
||||
{
|
||||
if (!source || !source->Account() || !c->ci || !cs_stats.HasExt(c->ci))
|
||||
if (!source || !source->IsIdentified() || !c->ci || !cs_stats.HasExt(c->ci))
|
||||
return;
|
||||
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);";
|
||||
query.SetValue("channel", c->name);
|
||||
@@ -555,7 +555,7 @@ public:
|
||||
private:
|
||||
void OnModeChange(Channel *c, User *u)
|
||||
{
|
||||
if (!u || !u->Account() || !c->ci || !cs_stats.HasExt(c->ci))
|
||||
if (!u || !u->IsIdentified() || !c->ci || !cs_stats.HasExt(c->ci))
|
||||
return;
|
||||
|
||||
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);";
|
||||
|
||||
@@ -72,6 +72,11 @@ class DBSQL final
|
||||
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)
|
||||
{
|
||||
if (!this->sql)
|
||||
@@ -124,8 +129,8 @@ public:
|
||||
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)
|
||||
{
|
||||
@@ -161,6 +166,14 @@ public:
|
||||
this->import = block->Get<bool>("import");
|
||||
}
|
||||
|
||||
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
|
||||
// connect to the uplink.
|
||||
SocketEngine::Process();
|
||||
}
|
||||
|
||||
void OnShutdown() override
|
||||
{
|
||||
this->shutting_down = true;
|
||||
@@ -209,7 +222,7 @@ public:
|
||||
return;
|
||||
Serialize::Type *s_type = obj->GetSerializableType();
|
||||
if (s_type && obj->id > 0)
|
||||
this->RunBackground("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + Anope::ToString(obj->id));
|
||||
this->RunBackground("DELETE FROM `" + GetTableName(s_type) + "` WHERE `id` = " + Anope::ToString(obj->id));
|
||||
this->updated_items.erase(obj);
|
||||
}
|
||||
|
||||
@@ -229,7 +242,7 @@ public:
|
||||
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)
|
||||
|
||||
@@ -53,13 +53,12 @@ private:
|
||||
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())
|
||||
{
|
||||
@@ -106,11 +105,11 @@ public:
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
std::vector<Query> create = this->SQL->CreateTable(this->prefix + s_type->GetName(), data);
|
||||
auto create = this->SQL->CreateTable(GetTableName(s_type), data);
|
||||
for (const auto &query : create)
|
||||
this->RunQueryResult(query);
|
||||
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 */
|
||||
@@ -163,7 +162,7 @@ public:
|
||||
if (s_type)
|
||||
{
|
||||
if (obj->id > 0)
|
||||
this->RunQuery("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + Anope::ToString(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);
|
||||
@@ -174,11 +173,11 @@ public:
|
||||
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)
|
||||
@@ -236,7 +235,7 @@ public:
|
||||
else
|
||||
{
|
||||
if (!s)
|
||||
this->RunQuery("UPDATE `" + prefix + obj->GetName() + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + Anope::ToString(id));
|
||||
this->RunQuery("UPDATE `" + GetTableName(obj) + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + Anope::ToString(id));
|
||||
else
|
||||
delete s;
|
||||
}
|
||||
@@ -245,7 +244,7 @@ public:
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ public:
|
||||
if (!blacklist.replies.empty() && !reply)
|
||||
return;
|
||||
|
||||
if (reply && reply->allow_account && user->Account())
|
||||
if (reply && reply->allow_account && user->IsIdentified())
|
||||
return;
|
||||
|
||||
Anope::string reason = this->blacklist.reason, addr = user->ip.addr();
|
||||
|
||||
+109
-16
@@ -159,28 +159,52 @@ public:
|
||||
|
||||
Anope::string FromUnixtime(time_t) override;
|
||||
|
||||
Anope::string GetColumnType(Serialize::DataType dt)
|
||||
const char* GetColumnDefault(Serialize::DataType dt)
|
||||
{
|
||||
switch (dt)
|
||||
{
|
||||
case Serialize::DataType::BOOL:
|
||||
return "TINYINT NOT NULL";
|
||||
|
||||
case Serialize::DataType::FLOAT:
|
||||
return "DOUBLE PRECISION NOT NULL";
|
||||
|
||||
case Serialize::DataType::INT:
|
||||
return "BIGINT NOT NULL";
|
||||
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 NOT NULL";
|
||||
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
|
||||
@@ -424,10 +448,79 @@ std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const D
|
||||
Result columns = this->RunQuery("SHOW COLUMNS FROM `" + table + "`");
|
||||
for (int i = 0; i < columns.Rows(); ++i)
|
||||
{
|
||||
const Anope::string &column = columns.Get(i, "Field");
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,7 +532,7 @@ std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const D
|
||||
{
|
||||
known_cols.insert(column);
|
||||
|
||||
query_text += ", `" + column + "` " + GetColumnType(data.GetType(column));
|
||||
query_text += ", `" + column + "` " + GetColumn(data.GetType(column));
|
||||
}
|
||||
query_text += ", PRIMARY KEY (`id`), KEY `timestamp_idx` (`timestamp`)) ROW_FORMAT=DYNAMIC";
|
||||
queries.push_back(query_text);
|
||||
@@ -453,7 +546,7 @@ std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const D
|
||||
|
||||
known_cols.insert(column);
|
||||
|
||||
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + column + "` " + GetColumnType(data.GetType(column));
|
||||
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + column + "` " + GetColumn(data.GetType(column));
|
||||
|
||||
queries.push_back(query_text);
|
||||
}
|
||||
@@ -467,7 +560,7 @@ Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Dat
|
||||
/* Empty columns not present in the data set */
|
||||
for (const auto &known_col : this->active_schema[table])
|
||||
{
|
||||
if (known_col != "id" && known_col != "timestamp" && data.data.count(known_col) == 0)
|
||||
if (data.data.count(known_col) == 0)
|
||||
data[known_col] << "";
|
||||
}
|
||||
|
||||
@@ -498,7 +591,7 @@ Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Dat
|
||||
case Serialize::DataType::UINT:
|
||||
{
|
||||
if (buf.empty())
|
||||
buf = "0";
|
||||
buf = "DEFAULT";
|
||||
escape = false;
|
||||
break;
|
||||
}
|
||||
@@ -507,7 +600,7 @@ Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Dat
|
||||
{
|
||||
if (buf.empty())
|
||||
{
|
||||
buf = "NULL";
|
||||
buf = "DEFAULT";
|
||||
escape = false;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -51,14 +51,14 @@ public:
|
||||
* @param sz How much to read
|
||||
* @return Number of bytes received
|
||||
*/
|
||||
int Recv(Socket *s, char *buf, size_t sz) 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) override;
|
||||
ssize_t Send(Socket *s, const char *buf, size_t sz) override;
|
||||
|
||||
/** Accept a connection from a socket
|
||||
* @param s The socket
|
||||
@@ -318,7 +318,7 @@ public:
|
||||
|
||||
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");
|
||||
@@ -339,7 +339,7 @@ public:
|
||||
GnuTLS::X509CertCredentials *newcred = new GnuTLS::X509CertCredentials(certfile, keyfile);
|
||||
|
||||
// DH params is not mandatory
|
||||
if (Anope::IsFile(dhfile.c_str()))
|
||||
if (Anope::IsFile(dhfile))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -384,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;
|
||||
@@ -411,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;
|
||||
|
||||
@@ -52,14 +52,14 @@ public:
|
||||
* @param sz How much to read
|
||||
* @return Number of bytes received
|
||||
*/
|
||||
int Recv(Socket *s, char *buf, size_t sz) 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) override;
|
||||
ssize_t Send(Socket *s, const char *buf, size_t sz) override;
|
||||
|
||||
/** Accept a connection from a socket
|
||||
* @param s The socket
|
||||
@@ -149,7 +149,7 @@ public:
|
||||
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");
|
||||
@@ -159,7 +159,7 @@ public:
|
||||
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");
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
}
|
||||
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;
|
||||
@@ -237,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)
|
||||
@@ -256,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)
|
||||
|
||||
+1
-1
@@ -169,7 +169,7 @@ public:
|
||||
}
|
||||
|
||||
// Command requires registered users only
|
||||
if (!cmd->AllowUnregistered() && !u->Account())
|
||||
if (!cmd->AllowUnregistered() && !u->IsIdentified())
|
||||
return;
|
||||
|
||||
if (params.size() < cmd->min_params)
|
||||
|
||||
+1
-1
@@ -192,7 +192,7 @@ public:
|
||||
* to has synced, or we'll get greet-floods when the net
|
||||
* recovers from a netsplit. -GD
|
||||
*/
|
||||
if (!c->ci || !c->ci->bi || !user->server->IsSynced() || !user->Account())
|
||||
if (!c->ci || !c->ci->bi || !user->server->IsSynced() || !user->IsIdentified())
|
||||
return;
|
||||
|
||||
Anope::string *greet = ns_greet.Get(user->Account());
|
||||
|
||||
@@ -157,7 +157,8 @@ public:
|
||||
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 %lu seconds before requesting a new vhost."), (unsigned long)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;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ void IRC2SQL::OnUserConnect(User *u, bool &exempt)
|
||||
query.SetValue("ident", u->GetIdent());
|
||||
query.SetValue("vident", u->GetVIdent());
|
||||
query.SetValue("secure", u->IsSecurelyConnected() ? "Y" : "N");
|
||||
query.SetValue("account", u->Account() ? u->Account()->display : "");
|
||||
query.SetValue("account", u->IsIdentified() ? u->Account()->display : "");
|
||||
query.SetValue("fingerprint", u->fingerprint);
|
||||
query.SetValue("signon", u->signon);
|
||||
query.SetValue("server", u->server->GetName());
|
||||
@@ -175,7 +175,7 @@ void IRC2SQL::OnUserLogin(User *u)
|
||||
{
|
||||
query = "UPDATE `" + prefix + "user` SET account=@account@ WHERE nick=@nick@";
|
||||
query.SetValue("nick", u->nick);
|
||||
query.SetValue("account", u->Account() ? u->Account()->display : "");
|
||||
query.SetValue("account", u->IsIdentified() ? u->Account()->display : "");
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
|
||||
+14
-14
@@ -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 "
|
||||
|
||||
@@ -145,7 +145,7 @@ public:
|
||||
{
|
||||
User *u = User::Find(uid);
|
||||
|
||||
if (!u || !u->Account() || r.empty())
|
||||
if (!u || !u->IsIdentified() || r.empty())
|
||||
return;
|
||||
|
||||
try
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
|
||||
void OnResult(const LDAPResult &r) override
|
||||
{
|
||||
if (!u || !u->Account())
|
||||
if (!u || !u->IsIdentified())
|
||||
return;
|
||||
|
||||
NickCore *nc = u->Account();
|
||||
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
{
|
||||
if (ci->AccessFor(cu->user).HasPriv("MEMO"))
|
||||
{
|
||||
if (cu->user->Account() && cu->user->Account()->HasExt("MEMO_RECEIVE"))
|
||||
if (cu->user->IsIdentified() && cu->user->Account()->HasExt("MEMO_RECEIVE"))
|
||||
cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), MemoServ->GetQueryCommand().c_str(), ci->name.c_str(), mi->memos->size());
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
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))
|
||||
|
||||
@@ -56,7 +56,11 @@ public:
|
||||
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 %lu seconds before using the %s command again."), Config->GetModule("memoserv")->Get<unsigned long>("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
|
||||
|
||||
@@ -55,7 +55,11 @@ public:
|
||||
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 %lu seconds before using the %s command again."), Config->GetModule("memoserv")->Get<unsigned long>("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());
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ class NickServRelease final
|
||||
|
||||
public:
|
||||
NickServRelease(Module *me, NickAlias *na, time_t delay)
|
||||
: User(na->nick, Config->GetModule("nickserv")->Get<const Anope::string>("enforceruser", "user"), Config->GetModule("nickserv")->Get<const Anope::string>("enforcerhost", Me->GetName()), "", "", Me, "Services Enforcer", Anope::CurTime, "", {}, IRCD->UID_Retrieve(), NULL)
|
||||
: User(na->nick, Config->GetModule(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)
|
||||
{
|
||||
@@ -140,12 +140,12 @@ class NickServCore final
|
||||
{
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +174,24 @@ public:
|
||||
OnShutdown();
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -238,30 +256,47 @@ public:
|
||||
|
||||
if (IRCD->CanSVSNick)
|
||||
{
|
||||
unsigned nicklen = IRCD->MaxNick;
|
||||
const Anope::string &guestprefix = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest");
|
||||
|
||||
auto guestnickok = false;
|
||||
Anope::string guestnick;
|
||||
|
||||
int i = 0;
|
||||
do
|
||||
for (auto i = 0; i < 10; ++i)
|
||||
{
|
||||
guestnick = guestprefix + Anope::ToString(static_cast<uint16_t>(Anope::RandomNumber()));
|
||||
if (guestnick.length() > nicklen)
|
||||
guestnick = guestnick.substr(0, nicklen);
|
||||
}
|
||||
while (User::Find(guestnick) && i++ < 10);
|
||||
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);
|
||||
}
|
||||
|
||||
if (i == 11)
|
||||
u->Kill(*NickServ, "Services nickname-enforcer kill");
|
||||
else
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
guestnickok = true;
|
||||
guestnick = u->GetUID();
|
||||
}
|
||||
|
||||
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) override
|
||||
@@ -400,7 +435,7 @@ public:
|
||||
const NickAlias *na = NickAlias::Find(u->nick);
|
||||
|
||||
const Anope::string &unregistered_notice = Config->GetModule(this)->Get<const Anope::string>("unregistered_notice");
|
||||
if (!Config->GetModule("nickserv")->Get<bool>("nonicknameownership") && !unregistered_notice.empty() && !na && !u->Account())
|
||||
if (!Config->GetModule("nickserv")->Get<bool>("nonicknameownership") && !unregistered_notice.empty() && !na && !u->IsIdentified())
|
||||
u->SendMessage(NickServ, unregistered_notice.replace_all_cs("%n", u->nick));
|
||||
else if (na && !u->IsIdentified(true))
|
||||
this->Validate(u);
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "module.h"
|
||||
#include "modules/ns_cert.h"
|
||||
|
||||
static ServiceReference<NickServService> nickserv("NickServService", "NickServ");
|
||||
|
||||
class NSGroupRequest final
|
||||
: public IdentifyRequest
|
||||
{
|
||||
@@ -142,13 +144,15 @@ public:
|
||||
}
|
||||
|
||||
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 %lu seconds before using the GROUP command again."), (unsigned long)(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;
|
||||
@@ -162,12 +166,8 @@ public:
|
||||
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;
|
||||
@@ -356,7 +356,7 @@ public:
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
source.Reply(_("%zu 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) override
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if (u->Account() && na && u->Account() == na->nc)
|
||||
if (u->IsIdentified() && na && u->Account() == na->nc)
|
||||
{
|
||||
source.Reply(_("You are already identified."));
|
||||
return;
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
static bool SendRegmail(User *u, const NickAlias *na, BotInfo *bi);
|
||||
|
||||
static ServiceReference<NickServService> nickserv("NickServService", "NickServ");
|
||||
|
||||
class CommandNSConfirm final
|
||||
: public Command
|
||||
{
|
||||
@@ -133,7 +135,6 @@ public:
|
||||
{
|
||||
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");
|
||||
@@ -154,18 +155,13 @@ public:
|
||||
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 %lu seconds to register."),
|
||||
(unsigned long)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;
|
||||
@@ -202,8 +198,9 @@ public:
|
||||
this->OnSyntaxError(source, "");
|
||||
else if (u && Anope::CurTime < u->lastnickreg + reg_delay)
|
||||
{
|
||||
source.Reply(_("Please wait %lu seconds before using the REGISTER command again."),
|
||||
(unsigned long)(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());
|
||||
|
||||
+5
-159
@@ -17,7 +17,7 @@ class CommandNSSet final
|
||||
public:
|
||||
CommandNSSet(Module *creator) : Command(creator, "nickserv/set", 1, 3)
|
||||
{
|
||||
this->SetDesc(_("Set options, including kill protection"));
|
||||
this->SetDesc(_("Set nickname options and information"));
|
||||
this->SetSyntax(_("\037option\037 \037parameters\037"));
|
||||
}
|
||||
|
||||
@@ -752,146 +752,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
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 ¶m)
|
||||
{
|
||||
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> ¶ms) 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> ¶ms) 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 CommandNSSASetNoexpire final
|
||||
: public Command
|
||||
{
|
||||
@@ -966,16 +826,13 @@ class NSSet final
|
||||
CommandNSSetKeepModes commandnssetkeepmodes;
|
||||
CommandNSSASetKeepModes commandnssasetkeepmodes;
|
||||
|
||||
CommandNSSetKill commandnssetkill;
|
||||
CommandNSSASetKill commandnssasetkill;
|
||||
|
||||
CommandNSSetPassword commandnssetpassword;
|
||||
CommandNSSASetPassword commandnssasetpassword;
|
||||
|
||||
CommandNSSASetNoexpire commandnssasetnoexpire;
|
||||
|
||||
SerializableExtensibleItem<bool> autoop, neverop, killprotect, kill_quick, kill_immed,
|
||||
noexpire;
|
||||
SerializableExtensibleItem<bool> autoop, neverop, noexpire;
|
||||
|
||||
struct KeepModes final
|
||||
: SerializableExtensibleItem<bool>
|
||||
@@ -1035,18 +892,13 @@ public:
|
||||
commandnssetdisplay(this), commandnssasetdisplay(this),
|
||||
commandnssetemail(this), commandnssasetemail(this),
|
||||
commandnssetkeepmodes(this), commandnssasetkeepmodes(this),
|
||||
commandnssetkill(this), commandnssasetkill(this),
|
||||
commandnssetpassword(this), commandnssasetpassword(this),
|
||||
commandnssasetnoexpire(this),
|
||||
|
||||
autoop(this, "AUTOOP"), neverop(this, "NEVEROP"),
|
||||
killprotect(this, "KILLPROTECT"), kill_quick(this, "KILL_QUICK"),
|
||||
kill_immed(this, "KILL_IMMED"),
|
||||
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> ¶ms) override
|
||||
@@ -1077,7 +929,7 @@ public:
|
||||
if (chan->ci)
|
||||
{
|
||||
/* Only give modes if autoop is set */
|
||||
give_modes &= !user->Account() || autoop.HasExt(user->Account());
|
||||
give_modes &= !user->IsIdentified() || autoop.HasExt(user->Account());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1092,12 +944,6 @@ public:
|
||||
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 (autoop.HasExt(na->nc))
|
||||
info.AddOption(_("Auto-op"));
|
||||
if (neverop.HasExt(na->nc))
|
||||
@@ -1110,13 +956,13 @@ public:
|
||||
|
||||
void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) override
|
||||
{
|
||||
if (u->Account() && setter.GetUser() == u)
|
||||
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->Account() && setter.GetUser() == u)
|
||||
if (u->IsIdentified() && setter.GetUser() == u)
|
||||
u->Account()->last_modes = u->GetModeList();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/* NickServ core functions
|
||||
*
|
||||
* (C) 2003-2024 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class 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 ¶m)
|
||||
{
|
||||
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> ¶ms) 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> ¶ms) 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)
|
||||
@@ -14,9 +14,13 @@
|
||||
class CommandNSSetLanguage
|
||||
: public Command
|
||||
{
|
||||
protected:
|
||||
Anope::map<Anope::string> &languages;
|
||||
|
||||
public:
|
||||
CommandNSSetLanguage(Module *creator, const Anope::string &sname = "nickserv/set/language", size_t min = 1)
|
||||
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"));
|
||||
@@ -43,27 +47,35 @@ public:
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
|
||||
if (param != "en_US")
|
||||
auto lang = languages.end();
|
||||
for (auto it = languages.begin(); it != languages.end(); ++it)
|
||||
{
|
||||
for (unsigned j = 0; j < Language::Languages.size(); ++j)
|
||||
auto &[langcode, langname] = *it;
|
||||
if (langcode.find_ci(param) != 0)
|
||||
continue; // Language does not match.
|
||||
|
||||
if (lang != languages.end())
|
||||
{
|
||||
if (Language::Languages[j] == param)
|
||||
break;
|
||||
else if (j + 1 == Language::Languages.size())
|
||||
{
|
||||
this->OnSyntaxError(source, "");
|
||||
return;
|
||||
}
|
||||
source.Reply(_("Multiple languages matched \002%s\002. Please be more specific."), param.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
lang = it;
|
||||
}
|
||||
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the language of " << nc->display << " to " << param;
|
||||
if (lang == languages.end())
|
||||
{
|
||||
this->OnSyntaxError(source, "");
|
||||
return;
|
||||
}
|
||||
|
||||
nc->language = param;
|
||||
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 \002English\002."));
|
||||
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(), Language::Translate(param.c_str(), _("English")));
|
||||
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> ¶m) override
|
||||
@@ -80,13 +92,8 @@ public:
|
||||
"\037language\037 should be chosen from the following list of\n"
|
||||
"supported languages:"));
|
||||
|
||||
source.Reply(" en_US (English)");
|
||||
for (const auto &language : Language::Languages)
|
||||
{
|
||||
const Anope::string &langname = Language::Translate(language.c_str(), _("English"));
|
||||
if (langname != "English")
|
||||
source.Reply(" %s (%s)", language.c_str(), langname.c_str());
|
||||
}
|
||||
for (const auto &[langcode, langname] : languages)
|
||||
source.Reply(" %s (%s)", langcode.c_str(), langname.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -96,8 +103,8 @@ class CommandNSSASetLanguage final
|
||||
: public CommandNSSetLanguage
|
||||
{
|
||||
public:
|
||||
CommandNSSASetLanguage(Module *creator)
|
||||
: CommandNSSetLanguage(creator, "nickserv/saset/language", 2)
|
||||
CommandNSSASetLanguage(Module *creator, Anope::map<Anope::string> &langs)
|
||||
: CommandNSSetLanguage(creator, langs, "nickserv/saset/language", 2)
|
||||
{
|
||||
this->ClearSyntax();
|
||||
this->SetSyntax(_("\037nickname\037 \037language\037"));
|
||||
@@ -116,13 +123,10 @@ public:
|
||||
"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_US (English)");
|
||||
for (const auto &language : Language::Languages)
|
||||
{
|
||||
const Anope::string &langname = Language::Translate(language.c_str(), _("English"));
|
||||
if (langname != "English")
|
||||
source.Reply(" %s (%s)", language.c_str(), langname.c_str());
|
||||
}
|
||||
|
||||
for (const auto &[langcode, langname] : languages)
|
||||
source.Reply(" %s (%s)", langcode.c_str(), langname.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -133,16 +137,23 @@ class NSSetLanguage final
|
||||
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)
|
||||
, commandnssasetlanguage(this)
|
||||
, 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")));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -292,7 +292,7 @@ public:
|
||||
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:
|
||||
|
||||
@@ -2134,12 +2134,12 @@ struct IRCDMessageIdle final
|
||||
{
|
||||
BotInfo *bi = BotInfo::Find(params[0]);
|
||||
if (bi)
|
||||
Uplink::Send(bi, "IDLE", source.GetSource(), Anope::StartTime, Anope::CurTime - bi->lastmsg);
|
||||
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(), Anope::StartTime, 0);
|
||||
Uplink::Send(u, "IDLE", source.GetSource(), u->signon, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -588,7 +588,7 @@ namespace UnrealExtBan
|
||||
if (e->GetMask() == "0" && !u->Account()) /* ~a:0 is special and matches all unauthenticated users */
|
||||
return true;
|
||||
|
||||
return u->Account() && Anope::Match(u->Account()->display, e->GetMask());
|
||||
return u->IsIdentified() && Anope::Match(u->Account()->display, e->GetMask());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
{
|
||||
SQLOperResultDeleter d(this);
|
||||
|
||||
if (!user || !user->Account())
|
||||
if (!user || !user->IsIdentified())
|
||||
return;
|
||||
|
||||
if (r.Rows() == 0)
|
||||
|
||||
@@ -226,7 +226,7 @@ private:
|
||||
request.reply("ip", u->ip.addr());
|
||||
request.reply("timestamp", Anope::ToString(u->timestamp));
|
||||
request.reply("signon", Anope::ToString(u->signon));
|
||||
if (u->Account())
|
||||
if (u->IsIdentified())
|
||||
{
|
||||
request.reply("account", iface->Sanitize(u->Account()->display));
|
||||
if (u->Account()->o)
|
||||
|
||||
@@ -118,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());
|
||||
|
||||
+1
-1
@@ -620,7 +620,7 @@ void Conf::Post(Conf *old)
|
||||
}
|
||||
}
|
||||
|
||||
Block *Conf::GetModule(Module *m)
|
||||
Block *Conf::GetModule(const Module *m)
|
||||
{
|
||||
if (!m)
|
||||
return NULL;
|
||||
|
||||
+1
-1
@@ -427,7 +427,7 @@ bool Anope::Init(int ac, char **av)
|
||||
|
||||
/* Chdir to Anope data directory. */
|
||||
Log() << "Moving to " << Anope::ServicesDir;
|
||||
if (chdir(Anope::ServicesDir.c_str()) < 0)
|
||||
if (chdir(Anope::ServicesDir.c_str()) != 0)
|
||||
{
|
||||
throw CoreException("Unable to chdir to " + Anope::ServicesDir + ": " + Anope::LastError());
|
||||
}
|
||||
|
||||
+82
-26
@@ -62,7 +62,7 @@ const char *Language::Translate(const char *string)
|
||||
|
||||
const char *Language::Translate(User *u, const char *string)
|
||||
{
|
||||
if (u && u->Account())
|
||||
if (u && u->IsIdentified())
|
||||
return Translate(u->Account(), string);
|
||||
else
|
||||
return Translate("", string);
|
||||
@@ -73,12 +73,67 @@ const char *Language::Translate(const NickCore *nc, const char *string)
|
||||
return Translate(nc ? nc->language.c_str() : "", string);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
+7
-5
@@ -217,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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -115,7 +115,7 @@ bool MemoInfo::HasIgnore(User *u)
|
||||
{
|
||||
for (const auto &ignore : this->ignores)
|
||||
{
|
||||
if (u->nick.equals_ci(ignore) || (u->Account() && u->Account()->display.equals_ci(ignore)) || Anope::Match(u->GetMask(), Anope::string(ignore)))
|
||||
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;
|
||||
|
||||
+43
-55
@@ -308,36 +308,32 @@ 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 Anope::ToString(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 = Anope::ToString(years) + " " + (years != 1 ? Language::Translate(nc, _("years")) : Language::Translate(nc, _("year")));
|
||||
need_comma = true;
|
||||
}
|
||||
if (days)
|
||||
{
|
||||
buffer += need_comma ? ", " : "";
|
||||
buffer += Anope::ToString(days) + " " + (days != 1 ? Language::Translate(nc, _("days")) : Language::Translate(nc, _("day")));
|
||||
need_comma = true;
|
||||
}
|
||||
if (hours)
|
||||
{
|
||||
buffer += need_comma ? ", " : "";
|
||||
buffer += Anope::ToString(hours) + " " + (hours != 1 ? Language::Translate(nc, _("hours")) : Language::Translate(nc, _("hour")));
|
||||
need_comma = true;
|
||||
}
|
||||
if (minutes)
|
||||
{
|
||||
buffer += need_comma ? ", " : "";
|
||||
buffer += Anope::ToString(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)
|
||||
@@ -359,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)
|
||||
|
||||
+11
-17
@@ -16,7 +16,7 @@
|
||||
#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")
|
||||
@@ -32,7 +32,7 @@ NickCore::NickCore(const Anope::string &coredisplay, uint64_t coreid)
|
||||
Log(LOG_DEBUG) << "Duplicate account " << this->display << " in NickCore table";
|
||||
|
||||
// Upgrading users may not have an account identifier.
|
||||
if (this->id && !NickCoreIdList.insert_or_assign(this->id, this).second)
|
||||
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));
|
||||
@@ -56,7 +56,7 @@ NickCore::~NickCore()
|
||||
|
||||
NickCoreList->erase(this->display);
|
||||
if (this->id)
|
||||
NickCoreIdList.erase(this->id);
|
||||
NickCoreIdList->erase(this->id);
|
||||
|
||||
if (!this->memos.memos->empty())
|
||||
{
|
||||
@@ -213,24 +213,18 @@ uint64_t NickCore::GetId()
|
||||
if (this->id)
|
||||
return this->id;
|
||||
|
||||
Anope::string secretid = this->display + "\0" + Anope::ToString(this->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 (auto &chr : key)
|
||||
chr = Anope::RandomNumber() % 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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
-139
@@ -1,139 +0,0 @@
|
||||
/* SipHash-2-4 routines.
|
||||
*
|
||||
* (C) 2003-2024 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*/
|
||||
|
||||
/* <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]; [[fallthrough]];
|
||||
case 6: pt[5] = m[5]; [[fallthrough]];
|
||||
case 5: pt[4] = m[4]; [[fallthrough]];
|
||||
case 4: *((uint32_t*)&pt[0]) = *((uint32_t*)&m[0]); break;
|
||||
case 3: pt[2] = m[2]; [[fallthrough]];
|
||||
case 2: pt[1] = m[1]; [[fallthrough]];
|
||||
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);
|
||||
}
|
||||
+5
-5
@@ -426,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());
|
||||
}
|
||||
|
||||
+4
-2
@@ -16,7 +16,8 @@ Timer::Timer(time_t time_from_now, bool repeating)
|
||||
, secs(time_from_now)
|
||||
, repeat(repeating)
|
||||
{
|
||||
TimerManager::AddTimer(this);
|
||||
if (time_from_now)
|
||||
TimerManager::AddTimer(this);
|
||||
}
|
||||
|
||||
Timer::Timer(Module *creator, time_t time_from_now, bool repeating)
|
||||
@@ -25,7 +26,8 @@ Timer::Timer(Module *creator, time_t time_from_now, bool repeating)
|
||||
, secs(time_from_now)
|
||||
, repeat(repeating)
|
||||
{
|
||||
TimerManager::AddTimer(this);
|
||||
if (time_from_now)
|
||||
TimerManager::AddTimer(this);
|
||||
}
|
||||
|
||||
Timer::~Timer()
|
||||
|
||||
@@ -328,6 +328,21 @@ void User::SendMessage(BotInfo *source, const char *fmt, ...)
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void User::SendMessage(BotInfo *source, int count, const char *singular, const char *plural, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[BUFSIZE] = "";
|
||||
|
||||
const char *translated_message = Language::Translate(this, count, singular, plural);
|
||||
|
||||
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)
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@
|
||||
|
||||
VERSION_MAJOR=2
|
||||
VERSION_MINOR=1
|
||||
VERSION_PATCH=10
|
||||
VERSION_PATCH=11
|
||||
VERSION_EXTRA=""
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
#include "pipe/pipe.h"
|
||||
#include "sigaction/sigaction.h"
|
||||
|
||||
typedef int ssize_t;
|
||||
typedef SSIZE_T ssize_t;
|
||||
|
||||
namespace Anope
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user