diff --git a/Core/addons/sourcemod/plugins/Keys_Core.smx b/Core/addons/sourcemod/plugins/Keys_Core.smx new file mode 100644 index 0000000..d15f3f0 Binary files /dev/null and b/Core/addons/sourcemod/plugins/Keys_Core.smx differ diff --git a/Core/addons/sourcemod/scripting/Keys_Core.smx b/Core/addons/sourcemod/scripting/Keys_Core.smx new file mode 100644 index 0000000..24ce6a2 Binary files /dev/null and b/Core/addons/sourcemod/scripting/Keys_Core.smx differ diff --git a/Core/addons/sourcemod/scripting/Keys_Core.sp b/Core/addons/sourcemod/scripting/Keys_Core.sp new file mode 100644 index 0000000..425513e --- /dev/null +++ b/Core/addons/sourcemod/scripting/Keys_Core.sp @@ -0,0 +1,222 @@ +#pragma semicolon 1 + +#include +#include + +#pragma newdecls required +#define PLUGIN_VERSION "2.0" + +public Plugin myinfo = +{ + name = "[Keys] Core", + author = "R1KO", + version = PLUGIN_VERSION, + url = "hlmod.ru" +}; + +#include "Keys/VARS.sp" +#include "Keys/UTIL.sp" +#include "Keys/KEYS.sp" +#include "Keys/API.sp" +#include "Keys/CMD.sp" +#include "Keys/EVENTS.sp" +#include "Keys/BLOCK.sp" +#include "Keys/STATS.sp" + +public void OnPluginStart() +{ + LoadTranslations("keys_core.phrases"); + + g_bIsStarted = false; + + BuildPath(Path_SM, SZF(g_sLogFile), "logs/Keys.log"); + + g_hKeysTrie = new StringMap(); + g_hKeysArray = new ArrayList(ByteCountToCells(KEYS_MAX_LENGTH)); + + CreateConVar("sm_keys_core_version", PLUGIN_VERSION, "KEYS-CORE VERSION", FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_CHEAT|FCVAR_DONTRECORD); + + ConVar hCvar = CreateConVar("key_length", "32", "Длина генерируемого ключа (8-64)", _, true, 8.0, true, 64.0); + hCvar.AddChangeHook(OnKeyLengthChange); + g_CVAR_iKeyLength = hCvar.IntValue; + + hCvar = CreateConVar("key_template", "", "Шаблон для генерируемого пароля (Подробнее http://hlmod.ru/resources/keys-core.438/)\n\ + Пример: XXXX-XXXX-XXXX-XXXX", _, false, 0.0, true, 64.0); + + hCvar.AddChangeHook(OnKeyTemplateChange); + hCvar.GetString(SZF(g_CVAR_sKeyTemplate)); + + hCvar = CreateConVar("key_server_id", "0", "ID сервера (0 - Не использовать. 1 и больше - Использовать указанный)", _, true, 0.0); + hCvar.AddChangeHook(OnServerIDChange); + g_CVAR_iServerID = hCvar.IntValue; + + hCvar = CreateConVar("key_attempts", "3", "Количество попыток ввода ключа до получения блокировки (0 - Отключено)", _, true, 0.0); + hCvar.AddChangeHook(OnAttemptsChange); + g_CVAR_iAttempts = hCvar.IntValue; + + hCvar = CreateConVar("key_block_time", "60", "На сколько минут будет заблокирован игрок при вводе неверных ключей (0 - Навсегда)", _, true, 0.0); + hCvar.AddChangeHook(OnBlockTimeChange); + g_CVAR_iBlockTime = hCvar.IntValue; + + Stats_OnPluginStart(); + + AutoExecConfig(true, "Keys_Core"); + + CMD_Reg(); + + Connect_DB(); +} + +public void OnKeyLengthChange(ConVar hCvar, const char[] oldValue, const char[] newValue) +{ + g_CVAR_iKeyLength = hCvar.IntValue; +} + +public void OnKeyTemplateChange(ConVar hCvar, const char[] oldValue, const char[] newValue) +{ + hCvar.GetString(SZF(g_CVAR_sKeyTemplate)); +} + +public void OnServerIDChange(ConVar hCvar, const char[] oldValue, const char[] newValue) +{ + g_CVAR_iServerID = hCvar.IntValue; +} + +public void OnAttemptsChange(ConVar hCvar, const char[] oldValue, const char[] newValue) +{ + g_CVAR_iAttempts = hCvar.IntValue; +} + +public void OnBlockTimeChange(ConVar hCvar, const char[] oldValue, const char[] newValue) +{ + g_CVAR_iBlockTime = hCvar.IntValue; +} + +void Connect_DB() +{ + if (SQL_CheckConfig("keys_core")) + { + Database.Connect(DB_OnConnect, "keys_core", 1); + } + else + { + char szError[PMP]; + szError[0] = '\0'; + g_hDatabase = SQLite_UseDatabase("keys_core", SZF(szError)); + DB_OnConnect(g_hDatabase, szError, 0); + } +} + +public void DB_OnConnect(Database hDatabase, const char[] szError, any data) +{ + if (hDatabase == null || szError[0]) + { + SetFailState("Failed DB Connect %s", szError); + return; + } + + g_hDatabase = hDatabase; + + char sDriver[16]; + g_hDatabase.Driver.GetIdentifier(SZF(sDriver)); + + g_bDBMySQL = (strcmp(sDriver, "mysql", false) == 0); + + if (g_bDBMySQL) + { + g_hDatabase.Query(SQL_Callback_ErrorCheck, "SET NAMES 'utf8'"); + g_hDatabase.Query(SQL_Callback_ErrorCheck, "SET CHARSET 'utf8'"); + } + + CreateTables(); +} + +void CreateTables() +{ + Transaction hTxn = new Transaction(); + + if (g_bDBMySQL) + { + hTxn.AddQuery("CREATE TABLE IF NOT EXISTS `keys_tokens` (\ + `k_id` INT UNSIGNED NOT NULL AUTO_INCREMENT, \ + `k_name` VARCHAR(64) NOT NULL, \ + `k_type` VARCHAR(64) NOT NULL, \ + `k_expires` INT UNSIGNED NOT NULL default 0, \ + `k_uses` INT UNSIGNED NOT NULL default 1, \ + `k_sid` INT UNSIGNED NOT NULL default 0, \ + PRIMARY KEY (`k_id`), \ + UNIQUE (`k_name`)) DEFAULT CHARSET=utf8;"); + + hTxn.AddQuery("CREATE TABLE IF NOT EXISTS `keys_params` (\ + `p_kid` INT UNSIGNED NOT NULL, \ + `p_num` TINYINT UNSIGNED NOT NULL, \ + `p_value` VARCHAR(64) NOT NULL) DEFAULT CHARSET=utf8;"); + + hTxn.AddQuery("CREATE TABLE IF NOT EXISTS `keys_block_players` (\ + `b_auth` VARCHAR(24) NOT NULL, \ + `b_end` INT UNSIGNED NOT NULL, \ + `b_sid` INT UNSIGNED NOT NULL default 0, \ + PRIMARY KEY (`b_auth`)) DEFAULT CHARSET=utf8;"); + + hTxn.AddQuery("CREATE TABLE IF NOT EXISTS `keys_players_used` (\ + `u_auth` VARCHAR(24) NOT NULL, \ + `u_kid` INT UNSIGNED NOT NULL, \ + `u_sid` INT UNSIGNED NOT NULL default 0) DEFAULT CHARSET=utf8;"); + } + else + { + hTxn.AddQuery("CREATE TABLE IF NOT EXISTS `keys_tokens` (\ + `k_id` INTEGER PRIMARY KEY AUTOINCREMENT, \ + `k_name` VARCHAR(64) NOT NULL UNIQUE, \ + `k_type` VARCHAR(64) NOT NULL, \ + `k_expires` INTEGER UNSIGNED NOT NULL default 0, \ + `k_uses` INTEGER UNSIGNED NOT NULL default 1);"); + + hTxn.AddQuery("CREATE TABLE IF NOT EXISTS `keys_params` (\ + `p_kid` INTEGER UNSIGNED NOT NULL, \ + `p_num` INTEGER UNSIGNED NOT NULL, \ + `p_value` VARCHAR(64) NOT NULL);"); + + hTxn.AddQuery("CREATE TABLE IF NOT EXISTS `keys_block_players` (\ + `b_auth` VARCHAR(24) NOT NULL PRIMARY KEY, \ + `b_end` INTEGER UNSIGNED NOT NULL);"); + + hTxn.AddQuery("CREATE TABLE IF NOT EXISTS `keys_players_used` (\ + `u_auth` VARCHAR(24) NOT NULL, \ + `u_kid` INTEGER UNSIGNED NOT NULL);"); + } + + g_hDatabase.Execute(hTxn, SQL_Callback_CreateTablesSuccess, SQL_Callback_CreateTablesFailure, 0, DBPrio_High); +} + +public void SQL_Callback_CreateTablesFailure(Database hDB, any data, int iNumQueries, const char[] szError, int iFailIndex, any[] queryData) +{ + SetFailState("Не удалось создать таблицу (%d): %s", iFailIndex, szError); +} + +public void SQL_Callback_CreateTablesSuccess(Database hDB, any data, int iNumQueries, DBResultSet[] hResults, any[] queryData) +{ + if(g_bDBMySQL) + { + g_hDatabase.SetCharset("utf8"); + } + + Notify_Started(); +} + +public void SQL_Callback_ErrorCheck(Database hDB, DBResultSet hResult, const char[] szError, any data) +{ + if (szError[0]) + { + LogError("SQL_Callback_ErrorCheck: %s", szError); + } +} + +void Notify_Started() +{ + g_bIsStarted = true; + + API_CreateForward_OnCoreStarted(); + + Keys_DeleteExpired(); +} \ No newline at end of file diff --git a/Core/addons/sourcemod/scripting/include/SteamWorks.inc b/Core/addons/sourcemod/scripting/include/SteamWorks.inc new file mode 100644 index 0000000..acd1dcc --- /dev/null +++ b/Core/addons/sourcemod/scripting/include/SteamWorks.inc @@ -0,0 +1,370 @@ +#if defined _SteamWorks_Included + #endinput +#endif +#define _SteamWorks_Included + +/* results from UserHasLicenseForApp */ +enum EUserHasLicenseForAppResult +{ + k_EUserHasLicenseResultHasLicense = 0, // User has a license for specified app + k_EUserHasLicenseResultDoesNotHaveLicense = 1, // User does not have a license for the specified app + k_EUserHasLicenseResultNoAuth = 2, // User has not been authenticated +}; + +/* General result codes */ +enum EResult +{ + k_EResultOK = 1, // success + k_EResultFail = 2, // generic failure + k_EResultNoConnection = 3, // no/failed network connection +// k_EResultNoConnectionRetry = 4, // OBSOLETE - removed + k_EResultInvalidPassword = 5, // password/ticket is invalid + k_EResultLoggedInElsewhere = 6, // same user logged in elsewhere + k_EResultInvalidProtocolVer = 7, // protocol version is incorrect + k_EResultInvalidParam = 8, // a parameter is incorrect + k_EResultFileNotFound = 9, // file was not found + k_EResultBusy = 10, // called method busy - action not taken + k_EResultInvalidState = 11, // called object was in an invalid state + k_EResultInvalidName = 12, // name is invalid + k_EResultInvalidEmail = 13, // email is invalid + k_EResultDuplicateName = 14, // name is not unique + k_EResultAccessDenied = 15, // access is denied + k_EResultTimeout = 16, // operation timed out + k_EResultBanned = 17, // VAC2 banned + k_EResultAccountNotFound = 18, // account not found + k_EResultInvalidSteamID = 19, // steamID is invalid + k_EResultServiceUnavailable = 20, // The requested service is currently unavailable + k_EResultNotLoggedOn = 21, // The user is not logged on + k_EResultPending = 22, // Request is pending (may be in process, or waiting on third party) + k_EResultEncryptionFailure = 23, // Encryption or Decryption failed + k_EResultInsufficientPrivilege = 24, // Insufficient privilege + k_EResultLimitExceeded = 25, // Too much of a good thing + k_EResultRevoked = 26, // Access has been revoked (used for revoked guest passes) + k_EResultExpired = 27, // License/Guest pass the user is trying to access is expired + k_EResultAlreadyRedeemed = 28, // Guest pass has already been redeemed by account, cannot be acked again + k_EResultDuplicateRequest = 29, // The request is a duplicate and the action has already occurred in the past, ignored this time + k_EResultAlreadyOwned = 30, // All the games in this guest pass redemption request are already owned by the user + k_EResultIPNotFound = 31, // IP address not found + k_EResultPersistFailed = 32, // failed to write change to the data store + k_EResultLockingFailed = 33, // failed to acquire access lock for this operation + k_EResultLogonSessionReplaced = 34, + k_EResultConnectFailed = 35, + k_EResultHandshakeFailed = 36, + k_EResultIOFailure = 37, + k_EResultRemoteDisconnect = 38, + k_EResultShoppingCartNotFound = 39, // failed to find the shopping cart requested + k_EResultBlocked = 40, // a user didn't allow it + k_EResultIgnored = 41, // target is ignoring sender + k_EResultNoMatch = 42, // nothing matching the request found + k_EResultAccountDisabled = 43, + k_EResultServiceReadOnly = 44, // this service is not accepting content changes right now + k_EResultAccountNotFeatured = 45, // account doesn't have value, so this feature isn't available + k_EResultAdministratorOK = 46, // allowed to take this action, but only because requester is admin + k_EResultContentVersion = 47, // A Version mismatch in content transmitted within the Steam protocol. + k_EResultTryAnotherCM = 48, // The current CM can't service the user making a request, user should try another. + k_EResultPasswordRequiredToKickSession = 49,// You are already logged in elsewhere, this cached credential login has failed. + k_EResultAlreadyLoggedInElsewhere = 50, // You are already logged in elsewhere, you must wait + k_EResultSuspended = 51, // Long running operation (content download) suspended/paused + k_EResultCancelled = 52, // Operation canceled (typically by user content download) + k_EResultDataCorruption = 53, // Operation canceled because data is ill formed or unrecoverable + k_EResultDiskFull = 54, // Operation canceled - not enough disk space. + k_EResultRemoteCallFailed = 55, // an remote call or IPC call failed + k_EResultPasswordUnset = 56, // Password could not be verified as it's unset server side + k_EResultExternalAccountUnlinked = 57, // External account (PSN, Facebook...) is not linked to a Steam account + k_EResultPSNTicketInvalid = 58, // PSN ticket was invalid + k_EResultExternalAccountAlreadyLinked = 59, // External account (PSN, Facebook...) is already linked to some other account, must explicitly request to replace/delete the link first + k_EResultRemoteFileConflict = 60, // The sync cannot resume due to a conflict between the local and remote files + k_EResultIllegalPassword = 61, // The requested new password is not legal + k_EResultSameAsPreviousValue = 62, // new value is the same as the old one ( secret question and answer ) + k_EResultAccountLogonDenied = 63, // account login denied due to 2nd factor authentication failure + k_EResultCannotUseOldPassword = 64, // The requested new password is not legal + k_EResultInvalidLoginAuthCode = 65, // account login denied due to auth code invalid + k_EResultAccountLogonDeniedNoMail = 66, // account login denied due to 2nd factor auth failure - and no mail has been sent + k_EResultHardwareNotCapableOfIPT = 67, // + k_EResultIPTInitError = 68, // + k_EResultParentalControlRestricted = 69, // operation failed due to parental control restrictions for current user + k_EResultFacebookQueryError = 70, // Facebook query returned an error + k_EResultExpiredLoginAuthCode = 71, // account login denied due to auth code expired + k_EResultIPLoginRestrictionFailed = 72, + k_EResultAccountLockedDown = 73, + k_EResultAccountLogonDeniedVerifiedEmailRequired = 74, + k_EResultNoMatchingURL = 75, + k_EResultBadResponse = 76, // parse failure, missing field, etc. + k_EResultRequirePasswordReEntry = 77, // The user cannot complete the action until they re-enter their password + k_EResultValueOutOfRange = 78, // the value entered is outside the acceptable range + k_EResultUnexpectedError = 79, // something happened that we didn't expect to ever happen + k_EResultDisabled = 80, // The requested service has been configured to be unavailable + k_EResultInvalidCEGSubmission = 81, // The set of files submitted to the CEG server are not valid ! + k_EResultRestrictedDevice = 82, // The device being used is not allowed to perform this action + k_EResultRegionLocked = 83, // The action could not be complete because it is region restricted + k_EResultRateLimitExceeded = 84, // Temporary rate limit exceeded, try again later, different from k_EResultLimitExceeded which may be permanent + k_EResultAccountLoginDeniedNeedTwoFactor = 85, // Need two-factor code to login + k_EResultItemDeleted = 86, // The thing we're trying to access has been deleted + k_EResultAccountLoginDeniedThrottle = 87, // login attempt failed, try to throttle response to possible attacker + k_EResultTwoFactorCodeMismatch = 88, // two factor code mismatch + k_EResultTwoFactorActivationCodeMismatch = 89, // activation code for two-factor didn't match + k_EResultAccountAssociatedToMultiplePartners = 90, // account has been associated with multiple partners + k_EResultNotModified = 91, // data not modified + k_EResultNoMobileDevice = 92, // the account does not have a mobile device associated with it + k_EResultTimeNotSynced = 93, // the time presented is out of range or tolerance + k_EResultSmsCodeFailed = 94, // SMS code failure (no match, none pending, etc.) + k_EResultAccountLimitExceeded = 95, // Too many accounts access this resource + k_EResultAccountActivityLimitExceeded = 96, // Too many changes to this account + k_EResultPhoneActivityLimitExceeded = 97, // Too many changes to this phone + k_EResultRefundToWallet = 98, // Cannot refund to payment method, must use wallet + k_EResultEmailSendFailure = 99, // Cannot send an email + k_EResultNotSettled = 100, // Can't perform operation till payment has settled + k_EResultNeedCaptcha = 101, // Needs to provide a valid captcha + k_EResultGSLTDenied = 102, // a game server login token owned by this token's owner has been banned + k_EResultGSOwnerDenied = 103, // game server owner is denied for other reason (account lock, community ban, vac ban, missing phone) + k_EResultInvalidItemType = 104 // the type of thing we were requested to act on is invalid +}; + +/* This enum is used in int client API methods, do not re-number existing values. */ +enum EHTTPMethod +{ + k_EHTTPMethodInvalid = 0, + k_EHTTPMethodGET, + k_EHTTPMethodHEAD, + k_EHTTPMethodPOST, + k_EHTTPMethodPUT, + k_EHTTPMethodDELETE, + k_EHTTPMethodOPTIONS, + + // The remaining HTTP methods are not yet supported, per rfc2616 section 5.1.1 only GET and HEAD are required for + // a compliant general purpose server. We'll likely add more as we find uses for them. + + // k_EHTTPMethodTRACE, + // k_EHTTPMethodCONNECT +}; + + +/* HTTP Status codes that the server can send in response to a request, see rfc2616 section 10.3 for descriptions + of each of these. */ +enum EHTTPStatusCode +{ + // Invalid status code (this isn't defined in HTTP, used to indicate unset in our code) + k_EHTTPStatusCodeInvalid = 0, + + // Informational codes + k_EHTTPStatusCode100Continue = 100, + k_EHTTPStatusCode101SwitchingProtocols = 101, + + // Success codes + k_EHTTPStatusCode200OK = 200, + k_EHTTPStatusCode201Created = 201, + k_EHTTPStatusCode202Accepted = 202, + k_EHTTPStatusCode203NonAuthoritative = 203, + k_EHTTPStatusCode204NoContent = 204, + k_EHTTPStatusCode205ResetContent = 205, + k_EHTTPStatusCode206PartialContent = 206, + + // Redirection codes + k_EHTTPStatusCode300MultipleChoices = 300, + k_EHTTPStatusCode301MovedPermanently = 301, + k_EHTTPStatusCode302Found = 302, + k_EHTTPStatusCode303SeeOther = 303, + k_EHTTPStatusCode304NotModified = 304, + k_EHTTPStatusCode305UseProxy = 305, + //k_EHTTPStatusCode306Unused = 306, (used in old HTTP spec, now unused in 1.1) + k_EHTTPStatusCode307TemporaryRedirect = 307, + + // Error codes + k_EHTTPStatusCode400BadRequest = 400, + k_EHTTPStatusCode401Unauthorized = 401, // You probably want 403 or something else. 401 implies you're sending a WWW-Authenticate header and the int client can sent an Authorization header in response. + k_EHTTPStatusCode402PaymentRequired = 402, // This is reserved for future HTTP specs, not really supported by int clients + k_EHTTPStatusCode403Forbidden = 403, + k_EHTTPStatusCode404NotFound = 404, + k_EHTTPStatusCode405MethodNotAllowed = 405, + k_EHTTPStatusCode406NotAcceptable = 406, + k_EHTTPStatusCode407ProxyAuthRequired = 407, + k_EHTTPStatusCode408RequestTimeout = 408, + k_EHTTPStatusCode409Conflict = 409, + k_EHTTPStatusCode410Gone = 410, + k_EHTTPStatusCode411LengthRequired = 411, + k_EHTTPStatusCode412PreconditionFailed = 412, + k_EHTTPStatusCode413RequestEntityTooLarge = 413, + k_EHTTPStatusCode414RequestURITooLong = 414, + k_EHTTPStatusCode415UnsupportedMediaType = 415, + k_EHTTPStatusCode416RequestedRangeNotSatisfiable = 416, + k_EHTTPStatusCode417ExpectationFailed = 417, + k_EHTTPStatusCode4xxUnknown = 418, // 418 is reserved, so we'll use it to mean unknown + k_EHTTPStatusCode429TooManyRequests = 429, + + // Server error codes + k_EHTTPStatusCode500InternalServerError = 500, + k_EHTTPStatusCode501NotImplemented = 501, + k_EHTTPStatusCode502BadGateway = 502, + k_EHTTPStatusCode503ServiceUnavailable = 503, + k_EHTTPStatusCode504GatewayTimeout = 504, + k_EHTTPStatusCode505HTTPVersionNotSupported = 505, + k_EHTTPStatusCode5xxUnknown = 599, +}; + +/* list of possible return values from the ISteamGameCoordinator API */ +enum EGCResults +{ + k_EGCResultOK = 0, + k_EGCResultNoMessage = 1, // There is no message in the queue + k_EGCResultBufferTooSmall = 2, // The buffer is too small for the requested message + k_EGCResultNotLoggedOn = 3, // The int client is not logged onto Steam + k_EGCResultInvalidMessage = 4, // Something was wrong with the message being sent with SendMessage +}; + +native bool SteamWorks_IsVACEnabled(); +native bool SteamWorks_GetPublicIP(int ipaddr[4]); +native int SteamWorks_GetPublicIPCell(); +native bool SteamWorks_IsLoaded(); +native bool SteamWorks_SetGameDescription(char[] sDesc); +native bool SteamWorks_IsConnected(); +native bool SteamWorks_SetRule(const char[] sKey, const char[] sValue); +native bool SteamWorks_ClearRules(); +native bool SteamWorks_ForceHeartbeat(); +native bool SteamWorks_GetUserGroupStatus(int client, int groupid); +native bool SteamWorks_GetUserGroupStatusAuthID(int authid, int groupid); + +native EUserHasLicenseForAppResult SteamWorks_HasLicenseForApp(int client, int app); +native EUserHasLicenseForAppResult SteamWorks_HasLicenseForAppId(int authid, int app); +native int SteamWorks_GetClientSteamID(int client, char[] sSteamID, int length); + +native bool SteamWorks_RequestStatsAuthID(int authid, int appid); +native bool SteamWorks_RequestStats(int client, int appid); +native bool SteamWorks_GetStatCell(int client, const char[] sKey, int &value); +native bool SteamWorks_GetStatAuthIDCell(int authid, const char[] sKey, int &value); +native bool SteamWorks_GetStatFloat(int client, const char[] sKey, float &value); +native bool SteamWorks_GetStatAuthIDFloat(int authid, const char[] sKey, float &value); + +native Handle SteamWorks_CreateHTTPRequest(EHTTPMethod method, const char[] sURL); +native bool SteamWorks_SetHTTPRequestContextValue(Handle hHandle, any data1, any data2=0); +native bool SteamWorks_SetHTTPRequestNetworkActivityTimeout(Handle hHandle, int timeout); +native bool SteamWorks_SetHTTPRequestHeaderValue(Handle hHandle, const char[] sName, const char[] sValue); +native bool SteamWorks_SetHTTPRequestGetOrPostParameter(Handle hHandle, const char[] sName, const char[] sValue); + +typeset SteamWorksHTTPRequestCompleted +{ + function void (Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode); + function void (Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, any data1); + function void (Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, any data1, any data2) +}; + +typeset SteamWorksHTTPHeadersReceived +{ + function void (Handle hRequest, bool bFailure); + function void (Handle hRequest, bool bFailure, any data1); + function void (Handle hRequest, bool bFailure, any data1, any data2) +}; + +typeset SteamWorksHTTPDataReceived +{ + function void (Handle hRequest, bool bFailure, int offset, int bytesreceived); + function void (Handle hRequest, bool bFailure, int offset, int bytesreceived, any data1); + function void (Handle hRequest, bool bFailure, int offset, int bytesreceived, any data1, any data2) +}; + +native bool SteamWorks_SetHTTPCallbacks(Handle hHandle, SteamWorksHTTPRequestCompleted fCompleted = INVALID_FUNCTION, SteamWorksHTTPHeadersReceived fHeaders = INVALID_FUNCTION, SteamWorksHTTPDataReceived fData = INVALID_FUNCTION, Handle hCalling = INVALID_HANDLE); +native bool SteamWorks_SendHTTPRequest(Handle hRequest); +native bool SteamWorks_SendHTTPRequestAndStreamResponse(Handle hRequest); +native bool SteamWorks_DeferHTTPRequest(Handle hRequest); +native bool SteamWorks_PrioritizeHTTPRequest(Handle hRequest); +native bool SteamWorks_GetHTTPResponseHeaderSize(Handle hRequest, const char[] sHeader, int &size); +native bool SteamWorks_GetHTTPResponseHeaderValue(Handle hRequest, const char[] sHeader, char[] sValue, int size); +native bool SteamWorks_GetHTTPResponseBodySize(Handle hRequest, int &size); +native bool SteamWorks_GetHTTPResponseBodyData(Handle hRequest, char[] sBody, int length); +native bool SteamWorks_GetHTTPStreamingResponseBodyData(Handle hRequest, int cOffset, char[] sBody, int length); +native bool SteamWorks_GetHTTPDownloadProgressPct(Handle hRequest, float &percent); +native bool SteamWorks_SetHTTPRequestRawPostBody(Handle hRequest, const char[] sContentType, const char[] sBody, int bodylen); + +typeset SteamWorksHTTPBodyCallback +{ + function void (const char[] sData); + function void (const char[] sData, any value); + function void (const int data, any value, int datalen); +}; + +native bool SteamWorks_GetHTTPResponseBodyCallback(Handle hRequest, SteamWorksHTTPBodyCallback fCallback, any data = 0, Handle hPlugin = INVALID_HANDLE); +native bool SteamWorks_WriteHTTPResponseBodyToFile(Handle hRequest, const char[] sFileName); + +forward void SW_OnValidateClient(int ownerauthid, int authid); +forward void SteamWorks_OnValidateClient(int ownerauthid, int authid); +forward void SteamWorks_SteamServersConnected(); +forward void SteamWorks_SteamServersConnectFailure(EResult result); +forward void SteamWorks_SteamServersDisconnected(EResult result); + +forward Action SteamWorks_RestartRequested(); +forward void SteamWorks_TokenRequested(char[] sToken, int maxlen); + +forward void SteamWorks_OnClientGroupStatus(int authid, int groupid, bool isMember, bool isOfficer); + +forward EGCResults SteamWorks_GCSendMessage(int unMsgType, const char[] pubData, int cubData); +forward void SteamWorks_GCMsgAvailable(int cubData); +forward EGCResults SteamWorks_GCRetrieveMessage(int punMsgType, const char[] pubDest, int cubDest, int pcubMsgSize); + +native EGCResults SteamWorks_SendMessageToGC(int unMsgType, const char[] pubData, int cubData); + +public Extension __ext_SteamWorks = +{ + name = "SteamWorks", + file = "SteamWorks.ext", +#if defined AUTOLOAD_EXTENSIONS + autoload = 1, +#else + autoload = 0, +#endif +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_EXTENSIONS +public void __ext_SteamWorks_SetNTVOptional() +{ + MarkNativeAsOptional("SteamWorks_IsVACEnabled"); + MarkNativeAsOptional("SteamWorks_GetPublicIP"); + MarkNativeAsOptional("SteamWorks_GetPublicIPCell"); + MarkNativeAsOptional("SteamWorks_IsLoaded"); + MarkNativeAsOptional("SteamWorks_SetGameDescription"); + MarkNativeAsOptional("SteamWorks_IsConnected"); + MarkNativeAsOptional("SteamWorks_SetRule"); + MarkNativeAsOptional("SteamWorks_ClearRules"); + MarkNativeAsOptional("SteamWorks_ForceHeartbeat"); + MarkNativeAsOptional("SteamWorks_GetUserGroupStatus"); + MarkNativeAsOptional("SteamWorks_GetUserGroupStatusAuthID"); + + MarkNativeAsOptional("SteamWorks_HasLicenseForApp"); + MarkNativeAsOptional("SteamWorks_HasLicenseForAppId"); + MarkNativeAsOptional("SteamWorks_GetClientSteamID"); + + MarkNativeAsOptional("SteamWorks_RequestStatsAuthID"); + MarkNativeAsOptional("SteamWorks_RequestStats"); + MarkNativeAsOptional("SteamWorks_GetStatCell"); + MarkNativeAsOptional("SteamWorks_GetStatAuthIDCell"); + MarkNativeAsOptional("SteamWorks_GetStatFloat"); + MarkNativeAsOptional("SteamWorks_GetStatAuthIDFloat"); + + MarkNativeAsOptional("SteamWorks_SendMessageToGC"); + + MarkNativeAsOptional("SteamWorks_CreateHTTPRequest"); + MarkNativeAsOptional("SteamWorks_SetHTTPRequestContextValue"); + MarkNativeAsOptional("SteamWorks_SetHTTPRequestNetworkActivityTimeout"); + MarkNativeAsOptional("SteamWorks_SetHTTPRequestHeaderValue"); + MarkNativeAsOptional("SteamWorks_SetHTTPRequestGetOrPostParameter"); + + MarkNativeAsOptional("SteamWorks_SetHTTPCallbacks"); + MarkNativeAsOptional("SteamWorks_SendHTTPRequest"); + MarkNativeAsOptional("SteamWorks_SendHTTPRequestAndStreamResponse"); + MarkNativeAsOptional("SteamWorks_DeferHTTPRequest"); + MarkNativeAsOptional("SteamWorks_PrioritizeHTTPRequest"); + MarkNativeAsOptional("SteamWorks_GetHTTPResponseHeaderSize"); + MarkNativeAsOptional("SteamWorks_GetHTTPResponseHeaderValue"); + MarkNativeAsOptional("SteamWorks_GetHTTPResponseBodySize"); + MarkNativeAsOptional("SteamWorks_GetHTTPResponseBodyData"); + MarkNativeAsOptional("SteamWorks_GetHTTPStreamingResponseBodyData"); + MarkNativeAsOptional("SteamWorks_GetHTTPDownloadProgressPct"); + MarkNativeAsOptional("SteamWorks_SetHTTPRequestRawPostBody"); + + MarkNativeAsOptional("SteamWorks_GetHTTPResponseBodyCallback"); + MarkNativeAsOptional("SteamWorks_WriteHTTPResponseBodyToFile"); +} +#endif diff --git a/Core/addons/sourcemod/scripting/include/cURL.inc b/Core/addons/sourcemod/scripting/include/cURL.inc new file mode 100644 index 0000000..0cb3199 --- /dev/null +++ b/Core/addons/sourcemod/scripting/include/cURL.inc @@ -0,0 +1,566 @@ + +#if defined _cURL_included + #endinput +#endif +#define _cURL_included + +#include + + +/* +======================================== +The Following CURLOPT_* NOT support: +ERRORBUFFER // use curl_get_error_buffer +WRITEINFO // ??? +PROGRESSFUNCTION // unused +PROGRESSDATA // same +HEADERFUNCTION // unused +DEBUGFUNCTION // unused +DEBUGDATA // same +SHARE // unsupport +PRIVATE // unsupport +SSL_CTX_FUNC // unused +SSL_CTX_DATA // same +IOCTLFUNCTION // unused +IOCTLDATA // same +CONV_FROM_NETWORK_FUNC // unused +CONV_TO_NETWORK_FUNC // unused +CONV_FROM_UTF8_FUNC // unused +SOCKOPTFUNCTION // unused +SOCKOPTDATA // unused +OPENSOCKETFUNCTION // used +OPENSOCKETDATA // used +COPYPOSTFIELDS // unsupport +SEEKFUNCTION // unused +SEEKDATA // unused +SOCKS5_GSSAPI_SERVICE // unsupport +SOCKS5_GSSAPI_NEC // unsupport +SSH_KEYFUNCTION // unsupport +SSH_KEYDATA // unsupport +INTERLEAVEFUNCTION // unsupport +CHUNK_BGN_FUNC // unsupport +CHUNK_END_FUNC // unsupport +FNMATCH_FUNC // unsupport +CHUNK_DATA // unsupport +FNMATCH_DATA // unsupport +TLSAUTH_USERNAME // unsupport, require tls-srp +TLSAUTH_PASSWORD // unsupport, require tls-srp +TLSAUTH_TYPE // unsupport, require tls-srp +CLOSESOCKETFUNCTION // unsupport +CLOSESOCKETDATA // unsupport +========================================*/ + +/* +======================================== +The Following CURLOPT_* supports the "file://" notation. +COOKIEFILE +COOKIEJAR +RANDOM_FILE +EGDSOCKET +SSLKEY +CAPATH +NETRC_FILE +SSH_PUBLIC_KEYFILE +SSH_PRIVATE_KEYFILE +_CRLFILE +ISSUERCERT +SSH_KNOWNHOSTS + +========================================*/ + +/* +======================================== +The Following CURLINFO_* NOT support: +CURLINFO_SLIST + +========================================*/ + +/* +======================================== +The Following CURLFORM_* NOT support: +CURLFORM_PTRNAME +CURLFORM_PTRCONTENTS +CURLFORM_ARRAY +CURLFORM_BUFFER +CURLFORM_BUFFERPTR +CURLFORM_BUFFERLENGTH +CURLFORM_STREAM + +========================================*/ + + + + +/*************************************************************************************************/ +/******************************************** OPTIONS ********************************************/ +/*************************************************************************************************/ + + +/** + * The Send & Receive Action + * Using on CURL_OnSend, CURL_OnReceive + * SendRecv_Act_GOTO_SEND = go to send + * SendRecv_Act_GOTO_RECV = go to receive + * SendRecv_Act_GOTO_WAIT = go to wait + * SendRecv_Act_GOTO_END = end the connection + * SendRecv_Act_GOTO_SEND_NO_WAIT = go to send but no select + * SendRecv_Act_GOTO_RECV_NO_WAIT = go to receive but no select + * To see how it work? see curl_echo_test.sp & curl_rcon_test.sp examples + */ +enum SendRecv_Act { + SendRecv_Act_NOTHING = 0, + + SendRecv_Act_GOTO_SEND, + SendRecv_Act_GOTO_RECV, + SendRecv_Act_GOTO_WAIT, + SendRecv_Act_GOTO_END, + SendRecv_Act_GOTO_SEND_NO_WAIT, + SendRecv_Act_GOTO_RECV_NO_WAIT, + + SendRecv_Act_LAST, +}; + +/** + * Hash type for curl_hash_file, curl_hash_string + */ +enum Openssl_Hash { + Openssl_Hash_MD5 = 0, + Openssl_Hash_MD4, + Openssl_Hash_MD2, + Openssl_Hash_SHA, + Openssl_Hash_SHA1, + Openssl_Hash_SHA224, + Openssl_Hash_SHA256, + Openssl_Hash_SHA384, + Openssl_Hash_SHA512, + Openssl_Hash_RIPEMD160, +}; + + +/*************************************************************************************************/ +/******************************************* CALLBACKS *******************************************/ +/*************************************************************************************************/ + + +/** + * called if curl_easy_perform_thread() or curl_easy_send_recv() Complete + * @ param Handle hndl The curl handle + * @ param CURLcode code The CURLcode code, see cURL_header.inc + * @ param any data Data passed to curl_easy_perform_thread() + * @ noreturn + */ +typeset CURL_OnComplete +{ + function void (Handle hndl, CURLcode code); + function void (Handle hndl, CURLcode code, any data); +}; + +/** + * called if curl_easy_send_recv() before sending data + * @ param Handle hndl The curl handle + * @ param CURLcode code The last CURLcode code, see cURL_header.inc + * @ param cell_t last_sent_dataSize The last sent datasize + * @ param any data Data passed to curl_easy_send_recv() + * @ return SendRecv_Act + */ +typeset CURL_OnSend +{ + function SendRecv_Act (Handle hndl, CURLcode code, const int last_sent_dataSize); + function SendRecv_Act (Handle hndl, CURLcode code, const int last_sent_dataSize, any data); +} + +/** + * called if curl_easy_send_recv() after received data + * @ param Handle hndl The curl handle + * @ param CURLcode code The CURLcode code, see cURL_header.inc + * @ param String dataSize The received datasize + * @ param any data Data passed to curl_easy_send_recv() + * @ return SendRecv_Act + */ +typeset CURL_OnReceive +{ + function SendRecv_Act (Handle hndl, CURLcode code, const char[] receiveData, const int dataSize); + function SendRecv_Act (Handle hndl, CURLcode code, const char[] receiveData, const int dataSize, any data); +} + +/** + * called if Openssl_Hash_file() after hashed the file + * @ param bool success True on success, false if hash file fail + * @ param String buffer The hash string + * @ param any data Data passed to Openssl_Hash_file() + * @ noreturn + */ +typeset Openssl_Hash_Complete +{ + function void (const bool success, const char[] buffer); + function void (const bool success, const char[] buffer, any data); +} + + +typeset CURL_Function_CB +{ + // CURLOPT_WRITEFUNCTION + function void (Handle hndl, const char[] buffer, const int bytes, const int nmemb); + function void (Handle hndl, const char[] buffer, const int bytes, const int nmemb, any data); + + // CURLOPT_READFUNCTION + function void (Handle hndl, const int bytes, const int nmemb); + function void (Handle hndl, const int bytes, const int nmemb, any data); +} + +/*************************************************************************************************/ +/******************************************** NATIVES ********************************************/ +/*************************************************************************************************/ + + +/** + * Create a curl handle + * @ return Handle The curl handle. Returns INVALID_HANDLE on failure + */ +native Handle curl_easy_init(); + +/** + * Set a curl option for CURLOPTTYPE_OBJECTPOINT type + * + * @ param Handle hndl The handle of the curl to be used. May be INVALID_HANDLE if not essential. + * @ param CURLoption opt The option to add (see enum CURLoption for details). + * @ param String buffer The value to set the option to. + * @ return bool 1 on success. 0 = The option not accept string or unsupport. + */ +native bool curl_easy_setopt_string(Handle hndl, CURLoption opt, const char[] buffer); + +/** + * Set a curl option for CURLOPTTYPE_LONG type + * + * @ param Handle hndl The handle of the curl to be used. May be INVALID_HANDLE if not essential. + * @ param CURLoption opt The option to add (see enum CURLoption for details). + * @ param cell_t value The value to set the option to. + * @ return bool 1 on success. 0 = The option not accept integer or unsupport. + */ +native bool curl_easy_setopt_int(Handle hndl, CURLoption opt, int value); + +/** + * Set a curl option for CURLOPTTYPE_LONG type + * @ example" + new opt[][2] = { + {_:CURLOPT_NOPROGRESS,1}, + {_:CURLOPT_VERBOSE,0} + }; + * + * @ param Handle hndl The handle of the curl to be used. May be INVALID_HANDLE if not essential. + * @ param cell_t array The option array to add (see enum CURLoption for details). + * @ param cell_t array_size The array size. + * @ return bool 1 on success. 0 = The option not accept integer or unsupport. + */ +native bool curl_easy_setopt_int_array(Handle hndl, array[][2], int array_size); + +/** + * Set a curl option for CURLOPTTYPE_OFF_T type + * + * @ param Handle hndl The handle of the curl to be used. May be INVALID_HANDLE if not essential. + * @ param CURLoption opt The option to add (see enum CURLoption for details). + * @ param String buffer The value to set the option to. + * @ return bool 1 on success. 0 = The option not accept string or unsupport. + */ +native bool curl_easy_setopt_int64(Handle hndl, CURLoption opt, const char[] buffer); + +/** + * Set a curl option for CURLOPTTYPE_OBJECTPOINT type + * @ note only accept the following handle type + curl_OpenFile() + curl_httppost() + curl_slist() + * + * @ param Handle hndl The handle of the curl to be used. May be INVALID_HANDLE if not essential. + * @ param CURLoption opt The option to add (see enum CURLoption for details). + * @ param Handle other_hndl The other handle to set the option to. + * @ return bool 1 on success. 0 = The option not accept string or unsupport. + */ +native bool curl_easy_setopt_handle(Handle hndl, CURLoption opt, Handle other_hndl); + +/** + * Set a curl option for CURLOPTTYPE_FUNCTIONPOINT type + * + * @ param Handle hndl The handle of the curl to be used. May be INVALID_HANDLE if not essential. + * @ param CURLoption opt The option to add (see enum CURLoption for details). + * @ param CURL_Function_CB callback The value to set the option to. + * @ param cell_t value Value to set. + * @ return bool 1 on success. 0 = The option unsupport or invalid callback function. + */ +native bool curl_easy_setopt_function(Handle hndl, CURLoption opt, CURL_Function_CB callback, any value=0); + +/** + * Load all CURLoption to curl Handle + * @ note + * Using curl_easy_perform_thread() will load option in thread + * Use this on curl_easy_perform or check all CURLoption are valid or not + * Only can use one time for each curl handle + * @ return The CURLcode code, see cURL_header.inc + */ +native CURLcode curl_load_opt(Handle hndl); + +/** + * Perform a file transfer + * @ return The CURLcode code, see cURL_header.inc + */ +native CURLcode curl_easy_perform(Handle hndl); + +/** + * Perform a file transfer, using thread + * @ param Handle hndl The handle of the curl to be used. May be INVALID_HANDLE if not essential. + * @ param CURL_OnComplete perform_callback The complete callback. + * @ param cell_t value Value to set. + * @ noreturn + */ +native void curl_easy_perform_thread(Handle hndl, CURL_OnComplete perform_callback, any value=0); + +/** + * Create a send & receive function for a connected curl handle + * @ param Handle hndl The handle of the curl to be used. + * @ param CURL_OnSend send_callback The send callback. + * @ param CURL_OnReceive receive_callback The receive callback. + * @ param CURL_OnComplete complete_callback The complete callback. + * @ param SendRecv_Act act The first SendRecv_Act action + * @ param cell_t send_timeout Send timeout value in milliseconds. + * @ param cell_t recv_timeout Receive timeout value in milliseconds. + * @ param cenn_t recv_buffer_Size Receive buffer size. + * @ param cell_t value Value to set. + * @ noreturn + */ +native void curl_easy_send_recv(Handle hndl, CURL_OnSend send_callback, CURL_OnReceive receive_callback, CURL_OnComplete complete_callback, SendRecv_Act act, int send_timeout, int recv_timeout, int recv_buffer_Size = 1024, any value=0); + +/** + * Send a signal to a send & receive curl handle + * @ param Handle hndl The handle of the send & receive curl to be used. + * @ param SendRecv_Act act The SendRecv_Act action after the singal + * @ return bool 1 on success. 0 = not a curl_easy_send_recv() curl, or not running/waiting + */ +native bool curl_send_recv_Signal(Handle hndl, SendRecv_Act act); + +/** + * Check send & receive curl handle is Waiting or not + * @ param Handle hndl The handle of the send & receive curl to be used. + * @ return bool 1 = is waiting. 0 = not a curl_easy_send_recv() curl, or not running/waiting + */ +native bool curl_send_recv_IsWaiting(Handle hndl); + +/** + * Send the send buffer for send & receive curl handle + * @ param Handle hndl The handle of the send & receive curl to be used. + * @ param cell_t data The data to send + * @ param cell_t size if specified the \0 terminator will not be included + * @ noreturn + */ +native void curl_set_send_buffer(Handle hndl, const char[] data, int size=-1); + +/** + * Send the receive data size for send & receive curl handle + * @ param Handle hndl The handle of the send & receive curl to be used. + * @ param cell_t size The receive size + * @ noreturn + */ +native void curl_set_receive_size(Handle hndl, int size); + +/** + * Set send timeout for curl_easy_send_recv() + * @ param Handle hndl The handle of the send & receive curl to be used. + * @ param cell_t timeout How long will try to send data before it timeout (milliseconds). + * @ noreturn + */ +native void curl_set_send_timeout(Handle hndl, int timeout); + +/** + * Set receive timeout for curl_easy_send_recv() + * @ param Handle hndl The handle of the send & receive curl to be used. + * @ param cell_t timeout How long will try to receive data before it timeout (milliseconds). + * @ noreturn + */ +native void curl_set_recv_timeout(Handle hndl, int timeout); + +/** + * Get CURLOPT_ERRORBUFFER error string in curl handle + * @ param Handle hndl The handle of the curl to be used. + * @ param String buffer Destination string buffer to copy to. + * @ param cell_t maxlen Destination buffer length (includes null terminator). + * @ noreturn + */ +native void curl_get_error_buffer(Handle hndl, char[] buffer, int maxlen); + +/** + * Extract information from a curl handle. (CURLINFO_STRING only) + * @ param Handle hndl The handle of the curl to be used. + * @ param CURLINFO info The enum CURLINFO, see cURL_header.inc + * @ param String buffer Destination string buffer to copy to. + * @ param cell_t maxlen Destination buffer length (includes null terminator). + * @ return The CURLcode code, see cURL_header.inc + */ +native CURLcode curl_easy_getinfo_string(Handle hndl, CURLINFO info, char[] buffer, int maxlen); + +/** + * Extract information from a curl handle. (CURLINFO_LONG, CURLINFO_DOUBLE only) + * @ param Handle hndl The handle of the curl to be used. + * @ param CURLINFO info The enum CURLINFO, see cURL_header.inc + * @ param value Variable to store the value. + * @ return The CURLcode code, see cURL_header.inc + */ +native CURLcode curl_easy_getinfo_int(Handle hndl, CURLINFO info, any &value); + +/** + * URL encodes the given string + * @ param Handle hndl The handle of the curl to be used. + * @ param String url The string to encodes. + * @ param String buffer Destination string buffer to copy to. + * @ param cell_t maxlen Destination buffer length (includes null terminator). + * @ return 1 on success. + */ +native bool curl_easy_escape(Handle hndl, const char[] url, char[] buffer, int maxlen); + +/** + * URL decodes the given string + * @ param Handle hndl The handle of the curl to be used. + * @ param String url The string to dencodes. + * @ param String buffer Destination string buffer to copy to. + * @ param cell_t maxlen Destination buffer length (includes null terminator). + * @ return The output length. + */ +native int curl_easy_unescape(Handle hndl, const char[] url, char[] buffer, int maxlen); + +/** + * Return string describing error code + * @ param CURLcode code The CURLcode code, see cURL_header.inc + * @ param String buffer Destination string buffer to copy to. + * @ param cell_t maxlen Destination buffer length (includes null terminator). + * @ noreturn + */ +native void curl_easy_strerror(CURLcode code, char[] buffer, int maxlen); + +/** + * Returns the libcurl version string + * @ param String buffer Destination string buffer to copy to. + * @ param cell_t maxlen Destination buffer length (includes null terminator). + * @ noreturn + */ +native void curl_version(char[] buffer, int maxlen); + +/** + * Returns the libcurl supported protocols string + * @ param String buffer Destination string buffer to copy to. + * @ param cell_t maxlen Destination buffer length (includes null terminator). + * @ noreturn + */ +native void curl_protocols(char[] buffer, int maxlen); + +/** + * Returns the libcurl supported features + * @ return The currently features bits. see CURL_VERSION_* + */ +native int curl_features(); + +/** + * This funcitopn same as Sourcemod OpenFile() + * For the following CUROPT_* only + * CURLOPT_WRITEDATA + * CURLOPT_HEADERDATA + * CURLOPT_READDATA + * CURLOPT_STDERR + * CURLOPT_INTERLEAVEDATA + * + * @ note + * Should not share to another threaded curl handle. + * + * @ param file File to open. + * @ param mode Open mode. + * @ return A Handle to the file, INVALID_HANDLE on open error. + */ +native Handle curl_OpenFile(const char[] file, const char[] mode); + + +/** + * Create a curl_httppost struct + * For the following CUROPT_* only + * CURLOPT_HTTPPOST + * @ note + * Should not share to another threaded curl handle. + * + * @ return A Handle to the curl_httppost, INVALID_HANDLE on error. + */ +native Handle curl_httppost(); + +/** + * Add a section to a multipart/formdata HTTP POST + * @ note + * Check enum CURLformoption (cURL_head.inc) to see which option supported + * + * @ param Handle hndl The handle of the curl_httppost to be used. + * @ param ... Variable number of format parameters. + * @ return The CURLFORMcode code, see cURL_header.inc + */ +native CURLFORMcode curl_formadd(Handle handl, any ...); + +/** + * Create a curl_slist struct + * For the following CUROPT_* only + * CURLOPT_QUOTE + * CURLOPT_HTTPHEADER + * CURLOPT_POSTQUOTE + * CURLOPT_TELNETOPTIONS + * CURLOPT_PREQUOTE + * CURLOPT_HTTP200ALIASES + * CURLOPT_MAIL_RCPT + * CURLOPT_RESOLVE + * + * @ note + * Should not share to another threaded curl handle. + * + * @ return A Handle to the curl_slist, INVALID_HANDLE on error. + */ +native Handle curl_slist(); + +/** + * Add a string to an slist + * @ param Handle hndl The handle of the curl_slist to be used. + * @ param String buffer The string to add + * @ noreturn + */ +native void curl_slist_append(Handle hndl, const char[] buffer); + +/** + * Hash a file + * @ parma String file The file path. supports the "file://" notation. + * @ param Openssl_Hash algorithm Hash Algorithm. + * @ param Openssl_Hash_Complete complete_callback The complete callback. + * @ param cell_t value Value to set. + * @ noreturn + */ +native void curl_hash_file(const char[] file, Openssl_Hash algorithm, Openssl_Hash_Complete complete_callback, any value=0); + +/** + * Hash a string + * @ parma String input The string to hash. + * @ param cell_t dataSize The input string size. + * @ param Openssl_Hash algorithm Hash Algorithm. + * @ param String buffer Destination string buffer to copy to. + * @ param cell_t maxlen Destination buffer length (includes null terminator). + * @ return 1 on success + */ +native bool curl_hash_string(const char[] input, int dataSize, Openssl_Hash algorithm, char[] buffer, int maxlength); + + +/** + * Do not edit below this line! + */ +public Extension __ext_curl = +{ + name = "curl", + file = "curl.ext", +#if defined AUTOLOAD_EXTENSIONS + autoload = 1, +#else + autoload = 0, +#endif +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; diff --git a/Core/addons/sourcemod/scripting/include/cURL_header.inc b/Core/addons/sourcemod/scripting/include/cURL_header.inc new file mode 100644 index 0000000..cf51cf1 --- /dev/null +++ b/Core/addons/sourcemod/scripting/include/cURL_header.inc @@ -0,0 +1,1206 @@ +#if defined _cURL_header_included + #endinput +#endif +#define _cURL_header_included + + +/* SourceMod */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define OFF_T CURLOPTTYPE_OFF_T + + +#define CURL_MAX_WRITE_SIZE 16384 + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* kerberos auth is supported */ +#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth support */ +#define CURL_VERSION_DEBUG (1<<6) /* built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* asynchronous dns resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth */ +#define CURL_VERSION_LARGEFILE (1<<9) /* supports files bigger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* International Domain Names support */ +#define CURL_VERSION_SSPI (1<<11) /* SSPI is supported */ +#define CURL_VERSION_CONV (1<<12) /* character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegating to winbind helper */ + + +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 + +#define CINIT(%1,%2,%3) CURLOPT_%1 = %2 + %3 + + /* three convenient "aliases" that follow the name scheme better */ +#define CURLOPT_WRITEDATA CURLOPT_FILE +#define CURLOPT_READDATA CURLOPT_INFILE +#define CURLOPT_HEADERDATA CURLOPT_WRITEHEADER +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +enum CURLoption { + /* This is the FILE * or void * the regular output should be written to. */ + CINIT(FILE, OBJECTPOINT, 1), + + /* The full URL to get/put */ + CINIT(URL, OBJECTPOINT, 2), + + /* Port number to connect to, if other than default. */ + CINIT(PORT, LONG, 3), + + /* Name of proxy to use. */ + CINIT(PROXY, OBJECTPOINT, 4), + + /* "name:password" to use when fetching. */ + CINIT(USERPWD, OBJECTPOINT, 5), + + /* "name:password" to use with proxy. */ + CINIT(PROXYUSERPWD, OBJECTPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CINIT(RANGE, OBJECTPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CINIT(INFILE, OBJECTPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. If this is not used, error messages go to stderr instead: */ + CINIT(ERRORBUFFER, OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CINIT(READFUNCTION, FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CINIT(TIMEOUT, LONG, 13), + + /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an OFF_T type, allowing platforms with larger OFF_T + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CINIT(INFILESIZE, LONG, 14), + + /* POST static input fields. */ + CINIT(POSTFIELDS, OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CINIT(REFERER, OBJECTPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CINIT(FTPPORT, OBJECTPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CINIT(USERAGENT, OBJECTPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CINIT(LOW_SPEED_LIMIT, LONG, 19), + + /* Set the "low speed time" */ + CINIT(LOW_SPEED_TIME, LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * OFF_T types, allowing for large file offsets on platforms which + * use larger-than-32-bit OFF_T's. Look below for RESUME_FROM_LARGE. + */ + CINIT(RESUME_FROM, LONG, 21), + + /* Set cookie in request: */ + CINIT(COOKIE, OBJECTPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind */ + CINIT(HTTPHEADER, OBJECTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CINIT(HTTPPOST, OBJECTPOINT, 24), + + /* name of the file keeping your private SSL-certificate */ + CINIT(SSLCERT, OBJECTPOINT, 25), + + /* password for the SSL or SSH private key */ + CINIT(KEYPASSWD, OBJECTPOINT, 26), + + /* send TYPE parameter? */ + CINIT(CRLF, LONG, 27), + + /* send linked-list of QUOTE commands */ + CINIT(QUOTE, OBJECTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CINIT(WRITEHEADER, OBJECTPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CINIT(COOKIEFILE, OBJECTPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CINIT(SSLVERSION, LONG, 32), + + /* What kind of HTTP time condition to use, see defines */ + CINIT(TIMECONDITION, LONG, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CINIT(TIMEVALUE, LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CINIT(CUSTOMREQUEST, OBJECTPOINT, 36), + + /* HTTP request, for odd commands like DELETE, TRACE and others */ + CINIT(STDERR, OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CINIT(POSTQUOTE, OBJECTPOINT, 39), + + /* Pass a pointer to string of the output using full variable-replacement + as described elsewhere. */ + CINIT(WRITEINFO, OBJECTPOINT, 40), /* DEPRECATED, do not use! */ + + CINIT(VERBOSE, LONG, 41), /* talk a lot */ + CINIT(HEADER, LONG, 42), /* throw the header out too */ + CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */ + CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */ + CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 300 */ + CINIT(UPLOAD, LONG, 46), /* this is an upload */ + CINIT(POST, LONG, 47), /* HTTP POST method */ + CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */ + + CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */ + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CINIT(NETRC, LONG, 51), + + CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */ + + CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */ + CINIT(PUT, LONG, 54), /* HTTP PUT */ + + /* 55 = OBSOLETE */ + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56), + + /* Data passed to the progress callback */ + CINIT(PROGRESSDATA, OBJECTPOINT, 57), + + /* We want the referrer field set automatically when following locations */ + CINIT(AUTOREFERER, LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CINIT(PROXYPORT, LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CINIT(POSTFIELDSIZE, LONG, 60), + + /* tunnel non-http operations through a HTTP proxy */ + CINIT(HTTPPROXYTUNNEL, LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CINIT(INTERFACE, OBJECTPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but doesn't match one of these, 'private' will be used. */ + CINIT(KRBLEVEL, OBJECTPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CINIT(SSL_VERIFYPEER, LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAINFO, OBJECTPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CINIT(MAXREDIRS, LONG, 68), + + /* Pass a LONG set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CINIT(FILETIME, LONG, 69), + + /* This points to a linked list of telnet options */ + CINIT(TELNETOPTIONS, OBJECTPOINT, 70), + + /* Max amount of cached alive connections */ + CINIT(MAXCONNECTS, LONG, 71), + + CINIT(CLOSEPOLICY, LONG, 72), /* DEPRECATED, do not use! */ + + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you're absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CINIT(FRESH_CONNECT, LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be re-used + when done. Do not use this unless you're absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CINIT(FORBID_REUSE, LONG, 75), + + /* Set to a file name that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CINIT(RANDOM_FILE, OBJECTPOINT, 76), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CINIT(EGDSOCKET, OBJECTPOINT, 77), + + /* Time-out connect operations after this amount of seconds, if connects + are OK within this time, then fine... This only aborts the connect + phase. [Only works on unix-style/SIGALRM operating systems] */ + CINIT(CONNECTTIMEOUT, LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CINIT(HTTPGET, LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CINIT(SSL_VERIFYHOST, LONG, 81), + + /* Specify which file name to write all known cookies in after completed + operation. Set file name to "-" (dash) to make it go to stdout. */ + CINIT(COOKIEJAR, OBJECTPOINT, 82), + + /* Specify which SSL ciphers to use */ + CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CINIT(HTTP_VERSION, LONG, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CINIT(FTP_USE_EPSV, LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CINIT(SSLCERTTYPE, OBJECTPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CINIT(SSLKEY, OBJECTPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CINIT(SSLKEYTYPE, OBJECTPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CINIT(SSLENGINE, OBJECTPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CINIT(SSLENGINE_DEFAULT, LONG, 90), + + /* Non-zero value means to use the global dns cache */ + CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */ + + /* DNS cache timeout */ + CINIT(DNS_CACHE_TIMEOUT, LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CINIT(PREQUOTE, OBJECTPOINT, 93), + + /* set the debug function */ + CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CINIT(DEBUGDATA, OBJECTPOINT, 95), + + /* mark this as start of a cookie session */ + CINIT(COOKIESESSION, LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAPATH, OBJECTPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CINIT(BUFFERSIZE, LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CINIT(NOSIGNAL, LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CINIT(SHARE, OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */ + CINIT(PROXYTYPE, LONG, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CINIT(ACCEPT_ENCODING, OBJECTPOINT, 102), + + /* Set pointer to private data */ + CINIT(PRIVATE, OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CINIT(HTTP200ALIASES, OBJECTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CINIT(UNRESTRICTED_AUTH, LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CINIT(FTP_USE_EPRT, LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(HTTPAUTH, LONG, 107), + + /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx + in second argument. The function must be matching the + curl_ssl_ctx_callback proto. */ + CINIT(SSL_CTX_FUNC, FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CINIT(SSL_CTX_DATA, OBJECTPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(PROXYAUTH, LONG, 111), + + /* FTP option that changes the timeout, in seconds, associated with + getting a response. This is different from transfer timeout time and + essentially places a demand on the FTP server to acknowledge commands + in a timely manner. */ + CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112), +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to resolve names to those IP versions only. This only has + affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CINIT(IPRESOLVE, LONG, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger OFF_T sizes. See MAXFILESIZE_LARGE below. */ + CINIT(MAXFILESIZE, LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CINIT(INFILESIZE_LARGE, OFF_T, 115), + + /* Sets the continuation offset. There is also a LONG version of this; + * look above for RESUME_FROM. + */ + CINIT(RESUME_FROM_LARGE, OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CINIT(MAXFILESIZE_LARGE, OFF_T, 117), + + /* Set this option to the file name of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CINIT(NETRC_FILE, OBJECTPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLFTPSSL_TRY - try using SSL, proceed anyway otherwise + CURLFTPSSL_CONTROL - SSL for the control connection or fail + CURLFTPSSL_ALL - SSL for all communication or fail + */ + CINIT(USE_SSL, LONG, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CINIT(TCP_NODELAY, LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CINIT(FTPSSLAUTH, LONG, 129), + + CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130), + CINIT(IOCTLDATA, OBJECTPOINT, 131), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* zero terminated string for pass on to the FTP server when asked for + "account" info */ + CINIT(FTP_ACCOUNT, OBJECTPOINT, 134), + + /* feed cookies into cookie engine */ + CINIT(COOKIELIST, OBJECTPOINT, 135), + + /* ignore Content-Length */ + CINIT(IGNORE_CONTENT_LENGTH, LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CINIT(FTP_SKIP_PASV_IP, LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CINIT(FTP_FILEMETHOD, LONG, 138), + + /* Local port number to bind the socket to */ + CINIT(LOCALPORT, LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CINIT(LOCALPORTRANGE, LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CINIT(CONNECT_ONLY, LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_FROM_NETWORK_FUNC, FUNCTIONPOINT, 142), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_TO_NETWORK_FUNC, FUNCTIONPOINT, 143), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CINIT(CONV_FROM_UTF8_FUNC, FUNCTIONPOINT, 144), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145), + CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147), + + /* callback function for setting socket options */ + CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148), + CINIT(SOCKOPTDATA, OBJECTPOINT, 149), + + /* set to 0 to disable session ID re-use for this transfer, default is + enabled (== 1) */ + CINIT(SSL_SESSIONID_CACHE, LONG, 150), + + /* allowed SSH authentication methods */ + CINIT(SSH_AUTH_TYPES, LONG, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CINIT(SSH_PUBLIC_KEYFILE, OBJECTPOINT, 152), + CINIT(SSH_PRIVATE_KEYFILE, OBJECTPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CINIT(FTP_SSL_CCC, LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CINIT(TIMEOUT_MS, LONG, 155), + CINIT(CONNECTTIMEOUT_MS, LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CINIT(HTTP_TRANSFER_DECODING, LONG, 157), + CINIT(HTTP_CONTENT_DECODING, LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CINIT(NEW_FILE_PERMS, LONG, 159), + CINIT(NEW_DIRECTORY_PERMS, LONG, 160), + + /* Set the behaviour of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CINIT(POSTREDIR, LONG, 161), + + /* used by scp/sftp to verify the host's public key */ + CINIT(SSH_HOST_PUBLIC_KEY_MD5, OBJECTPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163), + CINIT(OPENSOCKETDATA, OBJECTPOINT, 164), + + /* POST volatile input fields. */ + CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CINIT(PROXY_TRANSFER_MODE, LONG, 166), + + /* Callback function for seeking in the input stream */ + CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167), + CINIT(SEEKDATA, OBJECTPOINT, 168), + + /* CRL file */ + CINIT(CRLFILE, OBJECTPOINT, 169), + + /* Issuer certificate */ + CINIT(ISSUERCERT, OBJECTPOINT, 170), + + /* (IPv6) Address scope */ + CINIT(ADDRESS_SCOPE, LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. (Unfortunately) only + working with OpenSSL-powered builds. */ + CINIT(CERTINFO, LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CINIT(USERNAME, OBJECTPOINT, 173), + CINIT(PASSWORD, OBJECTPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CINIT(PROXYUSERNAME, OBJECTPOINT, 175), + CINIT(PROXYPASSWORD, OBJECTPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CINIT(NOPROXY, OBJECTPOINT, 177), + + /* block size for TFTP transfers */ + CINIT(TFTP_BLKSIZE, LONG, 178), + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_SERVICE, OBJECTPOINT, 179), + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_NEC, LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CINIT(PROTOCOLS, LONG, 181), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. Defaults + to all protocols except FILE and SCP. */ + CINIT(REDIR_PROTOCOLS, LONG, 182), + + /* set the SSH knownhost file name to use */ + CINIT(SSH_KNOWNHOSTS, OBJECTPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CINIT(SSH_KEYDATA, OBJECTPOINT, 185), + + /* set the SMTP mail originator */ + CINIT(MAIL_FROM, OBJECTPOINT, 186), + + /* set the SMTP mail receiver(s) */ + CINIT(MAIL_RCPT, OBJECTPOINT, 187), + + /* FTP: send PRET before PASV */ + CINIT(FTP_USE_PRET, LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CINIT(RTSP_REQUEST, LONG, 189), + + /* The RTSP session identifier */ + CINIT(RTSP_SESSION_ID, OBJECTPOINT, 190), + + /* The RTSP stream URI */ + CINIT(RTSP_STREAM_URI, OBJECTPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CINIT(RTSP_TRANSPORT, OBJECTPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CINIT(RTSP_CLIENT_CSEQ, LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CINIT(RTSP_SERVER_CSEQ, LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CINIT(INTERLEAVEDATA, OBJECTPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CINIT(WILDCARDMATCH, LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CINIT(CHUNK_BGN_FUNC, FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CINIT(CHUNK_END_FUNC, FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CINIT(FNMATCH_FUNC, FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CINIT(CHUNK_DATA, OBJECTPOINT, 201), + + /* FNMATCH_FUNC user pointer */ + CINIT(FNMATCH_DATA, OBJECTPOINT, 202), + + /* send linked-list of name:port:address sets */ + CINIT(RESOLVE, OBJECTPOINT, 203), + + /* Set a username for authenticated TLS */ + CINIT(TLSAUTH_USERNAME, OBJECTPOINT, 204), + + /* Set a password for authenticated TLS */ + CINIT(TLSAUTH_PASSWORD, OBJECTPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CINIT(TLSAUTH_TYPE, OBJECTPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + isn't any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CINIT(TRANSFER_ENCODING, LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208), + CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209), + + /* allow GSSAPI credential delegation */ + CINIT(GSSAPI_DELEGATION, LONG, 210), + + CURLOPT_LASTENTRY /* the last unused */ +}; + + +enum CURLcode { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_OBSOLETE10, /* 10 - NOT USED */ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_OBSOLETE12, /* 12 - NOT USED */ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_OBSOLETE16, /* 16 - NOT USED */ + CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error + instead of a memory allocation error if CURL_DOES_CONVERSIONS + is defined + */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ + CURLE_HTTP_POST_ERROR, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_FUNCTION_NOT_FOUND, /* 41 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint + wasn't verified fine */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_CONV_FAILED, /* 75 - conversion failed */ + CURLE_CONV_REQD, /* 76 - caller must register conversion + callbacks using curl_easy_setopt options + CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPT_CONV_TO_NETWORK_FUNCTION, and + CURLOPT_CONV_FROM_UTF8_FUNCTION */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it's ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + + CURL_LAST /* never use! */ +}; + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +enum curl_TimeCond { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +}; + +/* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +enum curl_closepolicy { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY, // CURLCLOSEPOLICY_LEAST_RECENTLY_USED + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +}; + +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd + like the library to choose the best possible + for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + + +#define CURLAUTH_NONE 0 /* nothing */ +#define CURLAUTH_BASIC (1<<0) /* Basic (default) */ +#define CURLAUTH_DIGEST (1<<1) /* Digest */ +#define CURLAUTH_GSSNEGOTIATE (1<<2) /* GSS-Negotiate */ +#define CURLAUTH_NTLM (1<<3) /* NTLM */ +#define CURLAUTH_DIGEST_IE (1<<4) /* Digest with IE flavour */ +#define CURLAUTH_NTLM_WB (1<<5) /* NTLM delegating to winbind helper */ +#define CURLAUTH_ONLY (1<<31) /* used together with a single other + type to force no auth or just that + single type */ +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) /* all fine types set */ +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +enum curl_ftpcreatedir { + CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ + CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ + CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +}; + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1 /* resolve to ipv4 addresses */ +#define CURL_IPRESOLVE_V6 2 /* resolve to ipv6 addresses */ + + +/* parameter for the CURLOPT_USE_SSL option */ +enum curl_usessl { + CURLUSESSL_NONE, /* do not attempt to use SSL */ + CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ + CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ + CURLUSESSL_ALL, /* SSL for all communication or fail */ + CURLUSESSL_LAST /* not an option, never use */ +}; + + +enum { + CURL_SSLVERSION_DEFAULT, + CURL_SSLVERSION_TLSv1, + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, + + CURL_SSLVERSION_LAST /* never use, keep last */ +}; + + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +enum curl_ftpauth { + CURLFTPAUTH_DEFAULT, /* let libcurl decide */ + CURLFTPAUTH_SSL, /* use "AUTH SSL" */ + CURLFTPAUTH_TLS, /* use "AUTH TLS" */ + CURLFTPAUTH_LAST /* not an option, never use */ +}; + + +enum curl_ftpfile { + FTPFILE_MULTICWD = 1, /* as defined by RFC1738 */ + FTPFILE_NOCWD = 2, /* use SIZE / RETR / STOR on the full path */ + FTPFILE_SINGLECWD = 3 /* make one CWD, then SIZE / RETR / STOR on the file */ +}; + + +#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */ + + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +enum curl_ftpccc { + CURLFTPSSL_CCC_NONE, /* do not send CCC */ + CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ + CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ + CURLFTPSSL_CCC_LAST /* not an option, never use */ +}; + + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301 and CURL_REDIR_POST_302 can be bitwise ORed so that + CURL_REDIR_POST_301 | CURL_REDIR_POST_302 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0 +#define CURL_REDIR_POST_301 1 +#define CURL_REDIR_POST_302 2 +#define CURL_REDIR_POST_ALL (CURL_REDIR_POST_301|CURL_REDIR_POST_302) + + +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_SCP (1<<4) +#define CURLPROTO_SFTP (1<<5) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_TFTP (1<<11) +#define CURLPROTO_IMAP (1<<12) +#define CURLPROTO_IMAPS (1<<13) +#define CURLPROTO_POP3 (1<<14) +#define CURLPROTO_POP3S (1<<15) +#define CURLPROTO_SMTP (1<<16) +#define CURLPROTO_SMTPS (1<<17) +#define CURLPROTO_RTSP (1<<18) +#define CURLPROTO_RTMP (1<<19) +#define CURLPROTO_RTMPT (1<<20) +#define CURLPROTO_RTMPE (1<<21) +#define CURLPROTO_RTMPTE (1<<22) +#define CURLPROTO_RTMPS (1<<23) +#define CURLPROTO_RTMPTS (1<<24) +#define CURLPROTO_GOPHER (1<<25) +#define CURLPROTO_ALL (~0) /* enable everything */ + + +/* + * Public API enums for RTSP requests + */ +enum { + CURL_RTSPREQ_NONE, /* first in list */ + CURL_RTSPREQ_OPTIONS, + CURL_RTSPREQ_DESCRIBE, + CURL_RTSPREQ_ANNOUNCE, + CURL_RTSPREQ_SETUP, + CURL_RTSPREQ_PLAY, + CURL_RTSPREQ_PAUSE, + CURL_RTSPREQ_TEARDOWN, + CURL_RTSPREQ_GET_PARAMETER, + CURL_RTSPREQ_SET_PARAMETER, + CURL_RTSPREQ_RECORD, + CURL_RTSPREQ_RECEIVE, + CURL_RTSPREQ_LAST /* last in list */ +}; + + + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +enum CURLINFO { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, + CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_CONTENT_LEN_DOWNLOAD = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LEN_UPLOAD = CURLINFO_DOUBLE + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_SLIST + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + /* Fill in new entries below here! */ + + CURLINFO_LASTONE = 42 +}; + + +enum curl_proxytype { + CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ + CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ + CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ + CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the + host name rather than the IP address. added + in 7.18.0 */ +}; + + +enum CURLformoption { + CURLFORM_NOTHING, /********* the first one is unused ************/ + /* */ + CURLFORM_COPYNAME, // char + CURLFORM_PTRNAME, // not support + CURLFORM_NAMELENGTH, // long + CURLFORM_COPYCONTENTS, // char + CURLFORM_PTRCONTENTS, // not support + CURLFORM_CONTENTSLENGTH, // long + CURLFORM_FILECONTENT, // char + CURLFORM_ARRAY, // not support + CURLFORM_OBSOLETE, + CURLFORM_FILE, // char + CURLFORM_BUFFER, // not support + CURLFORM_BUFFERPTR, // not support + CURLFORM_BUFFERLENGTH, // not support + CURLFORM_CONTENTTYPE, // char + CURLFORM_CONTENTHEADER, // curl_slist + CURLFORM_FILENAME, // char + CURLFORM_END, // !! + CURLFORM_OBSOLETE2, + CURLFORM_STREAM, // not support + CURLFORM_LASTENTRY /* the last unused */ +}; + +enum CURLFORMcode { + CURL_FORMADD_OK, /* first, no error */ + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ + CURL_FORMADD_LAST /* last */ +}; diff --git a/Core/addons/sourcemod/scripting/include/keys_core.inc b/Core/addons/sourcemod/scripting/include/keys_core.inc new file mode 100644 index 0000000..3290698 --- /dev/null +++ b/Core/addons/sourcemod/scripting/include/keys_core.inc @@ -0,0 +1,171 @@ +#if defined _keys_core_included + #endinput +#endif +#define _keys_core_included + +#define KEYS_MAX_LENGTH 64 + +enum KeysAction +{ + Validation = 0, // Валидация параметров ключа + Activation, // Активация ключа + Print // Вывод ключа в консоль/файл +}; + +enum KeysNativeAction +{ + Add = 0, // Добавление/Генерация ключа + Rem, // Удаление ключа + Use // Использование ключа +}; + +// Прототип вызова при валидации параметров/акцивации/выводе параметров ключа +typedef KeyActionCallback = function bool (KeysAction eKeysAction, int iClient, const char[] szKeyType, ArrayList hParamsArr, char[] szBuffer, int iBuffLen); + +typeset KeyInfoCallback +{ + // Прототип вызова при проверке существования ключа + function void (const char[] sKey, bool bKeyExists, any iData); + + // Прототип вызова при получении данных ключа + function void (const char[] sKey, bool bKeyExists, const char[] sKeyType, int iUses, int iExpires, ArrayList hParamsArr, any iData); +}; + +// Прототип вызова при добавлении/удалении/использовании ключа +typedef KeyNativeActionCallback = function void (KeysNativeAction eKeysAction, int iClient, const char[] sKey, bool bSuccess, const char[] sError, any iData); + +// Вызывается когда ядро было загружено +forward void Keys_OnCoreStarted(); + +// Загружено ли ядро +native bool Keys_IsCoreStarted(); + +// Получает Handle базы данных +native Database Keys_GetCoreDatabase(); + +// Получает тип базы данных (false - SQLite, true - MySQL) +native bool Keys_GetDatabaseType(); + +// Регистрирует тип ключей +native bool Keys_RegKey(const char[] sKeyType, KeyActionCallback fCallback); + +// Разрегистрирует тип ключей +native void Keys_UnregKey(const char[] sKeyType); + +// Проверяет существование типа ключей +native bool Keys_IsValidKeyType(const char[] sKeyType); + +// Получает adt_array со всеми типами ключей (нужно закрывать Handle) +native ArrayList Keys_FillArrayByKeyTypes(); + +// Проверяет существование ключа +native void Keys_IsValidKey(const char[] sKey, KeyInfoCallback IsValidKeyCallback, any iData = 0); + +// Получает данные ключа +native void Keys_GetKeyData(const char[] sKey, KeyInfoCallback GetKeyDataCallback, any iData = 0); + +// Генерирует ключ +native void Keys_GenerateKey(char[] sBuffer, int iBufLen, const char[] sTemplate = NULL_STRING); + +// Добавляет ключ +native void Keys_AddKey(int iClient = 0, const char[] sKey = NULL_STRING, const char[] sKeyType, int iUses, int iLifeTime, ArrayList hParamsArr, KeyNativeActionCallback AddKeyCallback, any iData = 0); + +// Удаляет ключ +native void Keys_RemoveKey(int iClient = 0, const char[] sKey, KeyNativeActionCallback RemoveKeyCallback, any iData = 0); + +// Использует ключ игроком +native void Keys_UseKey(int iClient, const char[] sKey, bool bNotify, bool bIgnoreBlock, KeyNativeActionCallback UseKeyCallback, any iData = 0); + +// Для использования не забыть +// LoadTranslations("keys_core.phrases"); +stock void Keys_GetTimeFromStamp(char[] sBuffer, int iMaxLength, int iTimeStamp, int iClient = LANG_SERVER) +{ + if (iTimeStamp > 31536000) + { + int iYears = iTimeStamp / 31536000; + int i = iTimeStamp - (iYears*31536000); + if(i > 2592000) + { + FormatEx(sBuffer, iMaxLength, "%d %T %d %T", iYears, "YEARS", iClient, i / 2592000, "MONTHS", iClient); + } + else + { + FormatEx(sBuffer, iMaxLength, "%d %T", iYears, "YEARS", iClient); + } + return; + } + + if (iTimeStamp > 2592000) + { + int iMonths = iTimeStamp / 2592000; + int i = iTimeStamp - (iMonths*2592000); + if (i > 86400) + { + FormatEx(sBuffer, iMaxLength, "%d %T %d %T", iMonths, "MONTHS", iClient, i / 86400, "DAYS", iClient); + } + else + { + FormatEx(sBuffer, iMaxLength, "%d %T", iMonths, "MONTHS", iClient); + } + return; + } + + if (iTimeStamp > 86400) + { + int iDays = iTimeStamp / 86400 % 365; + int iHours = (iTimeStamp / 3600) % 24; + if (iHours > 0) + { + FormatEx(sBuffer, iMaxLength, "%d %T %d %T", iDays, "DAYS", iClient, iHours, "HOURS", iClient); + } + else + { + FormatEx(sBuffer, iMaxLength, "%d %T", iDays, "DAYS", iClient); + } + return; + } + + int iHours = (iTimeStamp / 3600); + int iMins = (iTimeStamp / 60) % 60; + int iSecs = iTimeStamp % 60; + + if (iHours > 0) + { + FormatEx(sBuffer, iMaxLength, "%02d %02d %02d", iHours, iMins, iSecs); + } + else + { + FormatEx(sBuffer, iMaxLength, "%02d %02d", iMins, iSecs); + } +} + +public SharedPlugin __pl_keys_core= +{ + name = "keys_core", + file = "Keys_Core.smx", +#if defined REQUIRE_PLUGIN + required = 1 +#else + required = 0 +#endif +}; + +#if !defined REQUIRE_PLUGIN + +public void __pl_keys_core_SetNTVOptional() +{ + MarkNativeAsOptional("Keys_IsCoreStarted"); + MarkNativeAsOptional("Keys_GetCoreDatabase"); + MarkNativeAsOptional("Keys_GetDatabaseType"); + MarkNativeAsOptional("Keys_RegKey"); + MarkNativeAsOptional("Keys_UnregKey"); + MarkNativeAsOptional("Keys_IsValidKeyType"); + MarkNativeAsOptional("Keys_FillArrayByKeyTypes"); + MarkNativeAsOptional("Keys_IsValidKey"); + MarkNativeAsOptional("Keys_GetKeyData"); + MarkNativeAsOptional("Keys_GenerateKey"); + MarkNativeAsOptional("Keys_AddKey"); + MarkNativeAsOptional("Keys_RemoveKey"); + MarkNativeAsOptional("Keys_UseKey"); +} +#endif diff --git a/Core/addons/sourcemod/scripting/include/ripext.inc b/Core/addons/sourcemod/scripting/include/ripext.inc new file mode 100644 index 0000000..9fc02e3 --- /dev/null +++ b/Core/addons/sourcemod/scripting/include/ripext.inc @@ -0,0 +1,26 @@ +#if defined _ripext_included_ + #endinput +#endif +#define _ripext_included_ + +#include +#include + +/** + * Do not edit below this line! + */ +public Extension __ext_rip = +{ + name = "REST in Pawn", + file = "rip.ext", +#if defined AUTOLOAD_EXTENSIONS + autoload = 1, +#else + autoload = 0, +#endif +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; diff --git a/Core/addons/sourcemod/scripting/include/socket.inc b/Core/addons/sourcemod/scripting/include/socket.inc new file mode 100644 index 0000000..dd432ef --- /dev/null +++ b/Core/addons/sourcemod/scripting/include/socket.inc @@ -0,0 +1,462 @@ +// socket extension include file + +#if defined _socket_included + #endinput +#endif +#define _socket_included +#include + +enum SocketType { + SOCKET_TCP = 1, + SOCKET_UDP, + SOCKET_RAW +} + +#define EMPTY_HOST 1 +#define NO_HOST 2 +#define CONNECT_ERROR 3 +#define SEND_ERROR 4 +#define BIND_ERROR 5 +#define RECV_ERROR 6 +#define LISTEN_ERROR 7 + + +/*************************************************************************************************/ +/******************************************** options ********************************************/ +/*************************************************************************************************/ + + +/** + * Options available for SocketSetOption() + * + * @note modifying these options is not required for normal operation, you can skip the whole + * section in most cases. + */ +enum SocketOption { +/** + * If this option is set the socket extension will try to concatenate SocketReceive callbacks. + * + * This will possibly lower the amount of callbacks passed to SourceMod plugins and improve the + * performance. The socket extension will preserve the packet order. + * + * @note this doesn't prevent multiple callbacks, it only reduces them for high load. + * @note this will not truncate packets below 4096 bytes, setting it lower will be ignored + * @note set this option if you expect lots of data in a short timeframe + * @note don't forget to set your buffer sizes at least to the value passed to this function, but + * always at least to 4096 + * + * @param cell_t 0(=default) to disable or max. chunk size including \0 terminator in bytes + * @return bool true on success + */ + ConcatenateCallbacks = 1, +/** + * If this option is set the socket extension will enforce a mutex lock in the GameFrame() hook. + * + * This will ensure that callbacks will be processed every gameframe as fast as possible with the + * drawback of potentially creating lag. It's not recommended to set this option for most cases. + * If this option is not set the gameframe will be skipped if quietly obtaining a lock fails. + * + * @note combine this with CallbacksPerFrame for best performance + * @note this option will affect all sockets from all plugins, use it with caution! + * + * @param bool whether to force locking or not + * @return bool true on success + */ + ForceFrameLock, +/** + * This will specify the maximum amount of callbacks processed in every gameframe. + * + * The default value for this option is 1, setting it higher will possibly increase networking + * performance but may cause lag if it's set too high. + * The amount of callbacks actually being processed is limited by not being able to quietly obtain + * a lock (see ForceFrameLock) and the amount of callbacks in the queue. + * + * @note this option will affect all sockets from all plugins, use it with caution! + * + * @param cell_t maximum amount of callbacks per gameframe + * @return bool true on success + */ + CallbacksPerFrame, +/** + * If this option is set the socket will be allowed to send broadcast messages in case the protocol + * supports it. This is a wrapper for setting SO_BROADCAST. + * + * @param bool whether to allow broadcasting or not + * @return bool true on success + */ + SocketBroadcast, +/** + * If this option is set SocketBind() will allow reusing local adresses in case the protocol + * supports it. This is a wrapper for setting SO_REUSEADDR. + * + * @param bool whether to allow broadcasting or not + * @return bool true on success + */ + SocketReuseAddr, +/** + * If this option is set the socket will try to keep the connection alive by periodically sending + * messages if the protocol supports it. This is a wrapper for setting SO_KEEPALIVE. + * + * @param bool whether to allow broadcasting or not + * @return bool true on success + */ + SocketKeepAlive, +/** + * This option specifies how long a socket will wait if it's being closed and its send buffer is + * still filled. This is a wrapper for setting SO_LINGER. + * + * @param cell_t 0 (=default) to disable or time in s + * @return bool true on success + */ + SocketLinger, +/** + * If this option is set out-of-band data will be inlined into the normal receive stream. This is a + * wrapper for setting SO_OOBINLINE. + * + * @param bool whether to inline out-of-band data or not + * @return bool true on success + */ + SocketOOBInline, +/** + * This option specifies how large the send buffer will be. This is a wrapper for setting + * SO_SNDBUF. + * + * @param cell_t size in bytes + * @return bool true on success + */ + SocketSendBuffer, +/** + * This option specifies how large the receive buffer will be. This is a wrapper for setting + * SO_RCVBUF. + * + * @param cell_t size in bytes + * @return bool true on success + */ + SocketReceiveBuffer, +/** + * If this option is set outgoing messages will ignore the default routing facilities if the + * protocol implementation supports it. The remote site should be directly connected to the sender. + * This is a wrapper for setting SO_DONTROUTE. + * + * @param bool whether to skip default routing or not + * @return bool true on success + */ + SocketDontRoute, +/** + * This option specifies the minimum amount of data to receive before processing it. This is a + * wrapper for setting SO_RCVLOWAT. + * + * @note this can probably block the extension, use it with caution! + * + * @param cell_t size in bytes + * @return bool true on success + */ + SocketReceiveLowWatermark, +/** + * This option specifies how long a socket will try to receive data before it times out and + * processes the data. This is a wrapper for setting SO_RCVTIMEO. + * + * @param cell_t 0 (=default) to disable or time in ms + * @return bool true on success + */ + SocketReceiveTimeout, +/** + * This option specifies the minimum amount of data required in the send buffer before starting to + * send it. This is a wrapper for setting SO_SNDLOWAT. + * + * @note this can probably block the extension, use it with caution! + * + * @param cell_t size in bytes + * @return bool true on success + */ + SocketSendLowWatermark, +/** + * This option specifies how long a socket will try to send data before it times out and + * retries it later. This is a wrapper for setting SO_SNDTIMEO. + * + * @param cell_t 0 (=default) to disable or time in ms + * @return bool true on success + */ + SocketSendTimeout, +/** + * If this option is set the socket extension will display debugging messages in the server console/logs. + * + * @param bool whether to enable debugging or not + * @return bool true on success + */ + DebugMode +} + + +/*************************************************************************************************/ +/******************************************* callbacks *******************************************/ +/*************************************************************************************************/ + + +/** + * triggered if a normal sockets finished connecting and is ready to be used + * + * @param socket The socket handle pointing to the calling socket + * @param arg The argument set by SocketSetArg() + * @noreturn + */ +typedef SocketConnectCB = function void (Handle hSocket, any arg); + + +/** + * triggered if a listening socket received an incoming connection and is ready to be used + * + * @note The child-socket won't work until receive-, disconnect-, and errorcallback for it are set. + * + * @param Handle socket The socket handle pointing to the calling listen-socket + * @param Handle newSocket The socket handle to the newly spawned child socket + * @param String remoteIP The remote IP + * @param any arg The argument set by SocketSetArg() for the listen-socket + * @noreturn + */ +typedef SocketIncomingCB = function void (Handle hSocket, Handle hNewSocket, const char[] remoteIP, int remotePort, any arg); + +/** + * triggered if a socket receives data + * + * @note This is binary safe if you always use dataSize for operations on receiveData[] + * @note packets may be split up into multiple chunks -> multiple calls to the receive callback + * @note if not set otherwise by SocketSetOption(..., ConcatenateCallbacks, ...) receiveData will + * never be longer than 4096 characters including \0 terminator + * + * @param Handle socket The socket handle pointing to the calling socket + * @param String receiveData The data which arrived, 0-terminated at receiveData[dataSize] + * @param cell_t dataSize The length of the arrived data excluding the 0-termination + * @param any arg The argument set by SocketSetArg() for the socket + * @noreturn + */ +typedef SocketReceiveCB = function void (Handle hSocket, const char[] receiveData, const int dataSize, any arg); + +/** + * called after a socket sent all items in its send queue successfully + * + * @param Handle socket The socket handle pointing to the calling socket + * @param any arg The argument set by SocketSetArg() for the socket + * @noreturn + */ +typedef SocketSendqueueEmptyCB = function void (Handle hSocket, any arg); + +/** + * called if a socket has been properly disconnected by the remote side + * + * @note You should call CloseHandle(socket) or reuse the socket before this function ends + * + * @param Handle socket The socket handle pointing to the calling socket + * @param any arg The argument set by SocketSetArg() for the socket + * @noreturn + */ +typedef SocketDisconnectCB = function void (Handle hSocket, any arg); + +/** + * called if an unrecoverable error occured, close the socket without an additional call to a disconnect callback + * + * @note You should call CloseHandle(socket) or reuse the socket before this function ends + * + * @param Handle socket The socket handle pointing to the calling socket + * @param cell_t errorType The error type, see defines above + * @param cell_t errorNum The errno, see errno.h for details + * @param any arg The argument set by SocketSetArg() for the socket + * @noreturn + */ +typedef SocketErrorCB = function void (Handle hSocket, const int errorType, const int errorNum, any arg); + + +/*************************************************************************************************/ +/******************************************** natives ********************************************/ +/*************************************************************************************************/ + +/** + * Returns whether a socket is connected or not. + * + * @param socket Socket handle to check + * @return bool The connection status + */ +native bool SocketIsConnected(Handle hSocket); + + +/** + * Creates a new socket. + * + * @note this function may be relatively expensive, reuse sockets if possible + * + * @param SocketType protocol The protocol to use, SOCKET_TCP is default + * @param SocketErrorCB efunc The error callback + * @return Handle The socket handle. Returns INVALID_HANDLE on failure + */ +native Handle SocketCreate(SocketType protocol=SOCKET_TCP, SocketErrorCB efunc); + +/** + * Binds the socket to a local address + * + * @param Handle socket The handle of the socket to be used. * @param String hostname The hostname (or IP) to bind the socket to. + * @param cell_t port The port to bind the socket to. + * @return bool true on success + */ +native bool SocketBind(Handle hSocket, const char[] hostname, int port); + +/** + * Connects a socket + * + * @note this native is threaded, it may be still running after it executed, use the connect callback + * @note invokes the SocketError callback with errorType = CONNECT_ERROR or EMPTY_HOST if it fails + * @note invokes the SocketConnect callback if it succeeds + * + * @param Handle socket The handle of the socket to be used. + * @param SocketConnectCB cfunc The connect callback + * @param SocketReceiveCB rfunc The receive callback + * @param SocketDisconnectCB dfunc The disconnect callback * @param String hostname The hostname (or IP) to connect to. + * @param cell_t port The port to connect to. + * @noreturn + */ +native void SocketConnect(Handle hSocket, SocketConnectCB cfunc, SocketReceiveCB rfunc, SocketDisconnectCB dfunc, const char[] hostname, int port); + +/** + * Disconnects a socket + * + * @note this will not close the handle, the socket will be reset to a state similar to after SocketCreate() + * @note this won't trigger any disconnect/error callbacks + * + * @noreturn + */ +native bool SocketDisconnect(Handle hSocket); + +/** + * Makes a socket listen for incoming connections + * + * @param Handle socket The handle of the socket to be used. + * @param SocketIncomingCB ifunc The callback for incoming connections + * @return bool true on success + */ +native bool SocketListen(Handle hSocket, SocketIncomingCB ifunc); + +/** + * Sends data through the socket. + * + * @note specify size for binary safe operation + * @note if size is not specified the \0 terminator will not be included + * @note This native is threaded, it may be still running after it executed (not atomic). + * @note Use the SendqueueEmpty callback to determine when all data has been successfully sent. + * @note The socket extension will ensure that the data will be send in the correct order and split + * the data if required. + * + * @param Handle socket The handle of the socket to be used. + * @param String data The data to send. + * @noreturn */ +native void SocketSend(Handle hSocket, const char[] data, int size=-1); + +/** * Sends UDP data through the socket to a specific destination. + * + * @note specify size for binary safe operation + * @note if size is not specified the \0 terminator will not be included + * @note This native is threaded, it may be still running after it executed (not atomic). + * @note Use the SendqueueEmpty callback to determine when all data has been successfully sent. + * @note The socket extension will ensure that the data will be send in the correct order and split + * the data if required. + * + * @param Handle socket The handle of the socket to be used. + * @param String data The data to send. + * @param String hostname The hostname (or IP) to send to. + * @param cell_t port The port to send to. + * @noreturn */ +native void SocketSendTo(Handle hSocket, const char[] data, int size=-1, const char[] hostname, int port); + +/** + * Set a socket option. + * + * @param Handle socket The handle of the socket to be used. May be INVALID_HANDLE if not essential. + * @param SocketOption option The option to modify (see enum SocketOption for details). + * @param cellt_ value The value to set the option to. + * @return cell_t 1 on success. */ +native void SocketSetOption(Handle hSocket, SocketOption option, any value); + +/** + * Defines the callback function for when the socket receives data + * + * @note this is only useful and required for child-sockets spawned by listen-sockets + * (otherwise you already set it in SocketConnect()) + * + * @param Handle socket The handle of the socket to be used. + * @param SocketReceiveCB rfunc The receive callback + * @noreturn + */ +native void SocketSetReceiveCallback(Handle hSocket, SocketReceiveCB rfunc); + +/** + * Defines the callback function for when the socket sent all items in its send queue + * + * @note this must be called AFTER sending (queueing) the data + * @note if no send-data is queued this will fire the callback itself + * @note the callback is guaranteed to fire + * + * @param Handle socket The handle of the socket to be used. + * @param SocketDisconnectCB dfunc The disconnect callback + * @noreturn + */ +native void SocketSetSendqueueEmptyCallback(Handle hSocket, SocketSendqueueEmptyCB sfunc); + +/** + * Defines the callback function for when the socket was properly disconnected by the remote side + * + * @note this is only useful and required for child-sockets spawned by listen-sockets + * (otherwise you already set it in SocketConnect()) + * + * @param Handle socket The handle of the socket to be used. + * @param SocketDisconnectCB dfunc The disconnect callback + * @noreturn + */ +native void SocketSetDisconnectCallback(Handle hSocket, SocketDisconnectCB dfunc); + +/** + * Defines the callback function for when the socket triggered an error + * + * @note this is only useful and required for child-sockets spawned by listen-sockets + * (otherwise you already set it in SocketCreate()) + * + * @param Handle socket The handle of the socket to be used. + * @param SocketErrorCB efunc The error callback + * @noreturn + */ +native void SocketSetErrorCallback(Handle hSocket, SocketErrorCB efunc); + +/** + * Sets the argument being passed to callbacks + * + * @param Handle socket The handle of the socket to be used. + * @param any arg The argument to set + * @noreturn + */ +native void SocketSetArg(Handle hSocket, any arg); + +/** + * Retrieve the local system's hostname as the command "hostname" does. + * + * @param dest Destination string buffer to copy to. + * @param destLen Destination buffer length (includes null terminator). + * + * @return 1 on success + */ +native void SocketGetHostName(char[] dest, int destLen); + +/** + * _________________Do not edit below this line!_______________________ + */ +public Extension __ext_smsock = +{ + name = "Socket", + file = "socket.ext", +#if defined AUTOLOAD_EXTENSIONS + autoload = 1, +#else + autoload = 0, +#endif +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; diff --git a/Core/addons/sourcemod/scripting/keys/API.sp b/Core/addons/sourcemod/scripting/keys/API.sp new file mode 100644 index 0000000..0bbc2d1 --- /dev/null +++ b/Core/addons/sourcemod/scripting/keys/API.sp @@ -0,0 +1,417 @@ + +static Handle g_hGlobalForward_OnCoreStarted; + +public APLRes AskPluginLoad2(Handle hMySelf, bool bLate, char[] szError, int iErr_max) +{ + Stats_Init(); + + g_hGlobalForward_OnCoreStarted = CreateGlobalForward("Keys_OnCoreStarted", ET_Ignore); + + CreateNative("Keys_IsCoreStarted", Native_IsCoreStarted); + CreateNative("Keys_GetCoreDatabase", Native_GetCoreDatabase); + CreateNative("Keys_GetDatabaseType", Native_GetDatabaseType); + CreateNative("Keys_RegKey", Native_RegKey); + CreateNative("Keys_UnregKey", Native_UnregKey); + + CreateNative("Keys_IsValidKeyType", Native_IsValidKeyType); + CreateNative("Keys_FillArrayByKeyTypes", Native_FillArrayByKeyTypes); + + CreateNative("Keys_IsValidKey", Native_IsValidKey); + CreateNative("Keys_GetKeyData", Native_GetKeyData); + CreateNative("Keys_GenerateKey", Native_GenerateKey); + CreateNative("Keys_AddKey", Native_AddKey); + CreateNative("Keys_RemoveKey", Native_RemoveKey); + CreateNative("Keys_UseKey", Native_UseKey); + + RegPluginLibrary("keys_core"); + + return APLRes_Success; +} + +void API_CreateForward_OnCoreStarted() +{ + Call_StartForward(g_hGlobalForward_OnCoreStarted); + Call_Finish(); +} + +public int Native_IsCoreStarted(Handle hPlugin, int iNumParams) +{ + return view_as(g_bIsStarted); +} + +public int Native_GetCoreDatabase(Handle hPlugin, int iNumParams) +{ + return view_as(CloneHandle(g_hDatabase, hPlugin)); +} + +public int Native_GetDatabaseType(Handle hPlugin, int iNumParams) +{ + return view_as(g_bDBMySQL); +} + +public int Native_RegKey(Handle hPlugin, int iNumParams) +{ + char szKeyType[KEYS_MAX_LENGTH]; + GetNativeString(1, SZF(szKeyType)); + + if(g_hKeysArray.FindString(szKeyType) != -1) + { + ThrowNativeError(SP_ERROR_NATIVE, "Тип ключа \"%s\" уже зарегистрирован!", szKeyType); + return false; + } + + DataPack hDataPack = new DataPack(); + hDataPack.WriteCell(hPlugin); + hDataPack.WriteFunction(GetNativeCell(2)); + + g_hKeysTrie.SetValue(szKeyType, hDataPack); + g_hKeysArray.PushString(szKeyType); + + return true; +} + +public int Native_UnregKey(Handle hPlugin, int iNumParams) +{ + char szKeyType[KEYS_MAX_LENGTH]; + GetNativeString(1, SZF(szKeyType)); + + int index; + if((index = g_hKeysArray.FindString(szKeyType)) != -1) + { + g_hKeysArray.Erase(index); + DataPack hDataPack; + if(g_hKeysTrie.GetValue(szKeyType, hDataPack)) + { + delete hDataPack; + } + g_hKeysTrie.Remove(szKeyType); + } +} + +public int Native_IsValidKeyType(Handle hPlugin, int iNumParams) +{ + char szKeyType[KEYS_MAX_LENGTH]; + GetNativeString(1, SZF(szKeyType)); + + return (FindStringInArray(g_hKeysArray, szKeyType) != -1); +} + +public int Native_FillArrayByKeyTypes(Handle hPlugin, int iNumParams) +{ + return view_as(g_hKeysArray.Clone()); +} + +public int Native_IsValidKey(Handle hPlugin, int iNumParams) +{ + char szKey[KEYS_MAX_LENGTH], szQuery[PMP], szSID[64]; + GetNativeString(1, SZF(szKey)); + + DataPack hDP = new DataPack(); + hDP.WriteCell(hPlugin); + hDP.WriteFunction(GetNativeCell(2)); + hDP.WriteString(szKey); + hDP.WriteCell(GetNativeCell(3)); + + if(!g_CVAR_iServerID) + { + szSID[0] = 0; + } + else + { + FormatEx(SZF(szSID), " AND `k_sid` = %d", g_CVAR_iServerID); + } + + FormatEx(SZF(szQuery), "SELECT `k_id` FROM `keys_tokens` WHERE `k_name` = '%s'%s LIMIT 1;", szKey, szSID); + + g_hDatabase.Query(SQL_Callback_Ntv_IsValidKey, szQuery, hDP); +} + +public void SQL_Callback_Ntv_IsValidKey(Database hDB, DBResultSet hResult, const char[] szDbError, any hCbDP) +{ + DataPack hDP = view_as(hCbDP); + + if (hResult == null || szDbError[0]) + { + delete hDP; + LogError("SQL_Callback_Ntv_IsValidKey: %s", szDbError); + return; + } + + hDP.Reset(); + Handle hPlugin = view_as(hDP.ReadCell()); + Function fCallback = hDP.ReadFunction(); + char szKey[KEYS_MAX_LENGTH]; + hDP.ReadString(SZF(szKey)); + any iData = hDP.ReadCell(); + delete hDP; + + bool bKeyExists = false; + + if(hResult.FetchRow()) + { + int iExpires = hResult.FetchInt(0); + if(iExpires) + { + if(iExpires < GetTime()) + { + Keys_Delete(szKey); + } + else + { + bKeyExists = true; + } + } + else + { + bKeyExists = true; + } + } + + Call_StartFunction(hPlugin, fCallback); + Call_PushString(szKey); + Call_PushCell(bKeyExists); + Call_PushCell(iData); + Call_Finish(); +} + +public int Native_GetKeyData(Handle hPlugin, int iNumParams) +{ + char szKey[KEYS_MAX_LENGTH], szQuery[PMP], szSID[64]; + GetNativeString(1, SZF(szKey)); + + DataPack hDP = new DataPack(); + hDP.WriteCell(hPlugin); + hDP.WriteFunction(GetNativeCell(2)); + hDP.WriteString(szKey); + hDP.WriteCell(GetNativeCell(3)); + + if(!g_CVAR_iServerID) + { + szSID[0] = 0; + } + else + { + FormatEx(SZF(szSID), " AND `k_sid` = %d", g_CVAR_iServerID); + } + + FormatEx(SZF(szQuery), "SELECT `k_id`, `k_type`, `k_expires`, `k_uses` FROM `keys_tokens` WHERE `k_name` = '%s'%s LIMIT 1;", szKey, szSID); + + g_hDatabase.Query(SQL_Callback_Ntv_GetKeyData, szQuery, hDP); +} + +public void SQL_Callback_Ntv_GetKeyData(Database hDB, DBResultSet hResult, const char[] szDbError, any hCbDP) +{ + DataPack hDP = view_as(hCbDP); + + if (hResult == null || szDbError[0]) + { + delete hDP; + LogError("SQL_Callback_Ntv_GetKeyData: %s", szDbError); + return; + } + + hDP.Reset(); + + char szKey[KEYS_MAX_LENGTH], szKeyType[KEYS_MAX_LENGTH]; + Handle hPlugin = view_as(hDP.ReadCell()); + Function fCallback = hDP.ReadFunction(); + hDP.ReadString(SZF(szKey)); + any iData = hDP.ReadCell(); + + bool bKeyExists = false; + int iKeyID, iExpires, iUses; + + if(hResult.FetchRow()) + { + iExpires = hResult.FetchInt(2); + if(!iExpires || iExpires > GetTime()) + { + hResult.FetchString(1, SZF(szKeyType)); + if(g_hKeysArray.FindString(szKeyType) != -1) + { + iUses = hResult.FetchInt(3); + if(iUses) + { + bKeyExists = true; + iKeyID = hResult.FetchInt(0); + } + else + { + Keys_Delete(szKey); + } + } + } + else + { + Keys_Delete(szKey); + } + } + + if(!bKeyExists) + { + Call_StartFunction(hPlugin, fCallback); + Call_PushString(szKey); + Call_PushCell(false); + Call_PushString(NULL_STRING); + Call_PushCell(0); + Call_PushCell(0); + Call_PushCell(0); + Call_PushCell(iData); + Call_Finish(); + delete hDP; + return; + } + + hDP.WriteString(szKeyType); + hDP.WriteCell(iUses); + hDP.WriteCell(iExpires); + + char szQuery[PMP]; + + FormatEx(SZF(szQuery), "SELECT `p_num`, `p_value` FROM `keys_params` WHERE `p_kid` = '%d' ORDER BY `p_num`;", iKeyID); + + g_hDatabase.Query(SQL_Callback_Ntv_GetKeyDataParams, szQuery, hDP); +} + +public void SQL_Callback_Ntv_GetKeyDataParams(Database hDB, DBResultSet hResult, const char[] szDbError, any hCbDP) +{ + DataPack hDP = view_as(hCbDP); + + if (hResult == null || szDbError[0]) + { + delete hDP; + LogError("SQL_Callback_Ntv_GetKeyDataParams: %s", szDbError); + return; + } + + hDP.Reset(); + + char szKey[KEYS_MAX_LENGTH], szKeyType[KEYS_MAX_LENGTH], szParam[KEYS_MAX_LENGTH]; + Handle hPlugin = view_as(hDP.ReadCell()); + Function fCallback = hDP.ReadFunction(); + hDP.ReadString(SZF(szKey)); + any iData = hDP.ReadCell(); + hDP.ReadString(SZF(szKeyType)); + int iUses = hDP.ReadCell(); + int iExpires = hDP.ReadCell(); + delete hDP; + + ArrayList hParamsArr = new ArrayList(ByteCountToCells(KEYS_MAX_LENGTH)); + while(hResult.FetchRow()) + { + hResult.FetchString(1, SZF(szParam)); + hParamsArr.PushString(szParam); + } + + Call_StartFunction(hPlugin, fCallback); + Call_PushString(szKey); + Call_PushCell(true); + Call_PushString(szKeyType); + Call_PushCell(iUses); + Call_PushCell(iExpires); + Call_PushCell(hParamsArr); + Call_PushCell(iData); + Call_Finish(); +} + +public int Native_GenerateKey(Handle hPlugin, int iNumParams) +{ + char szKey[KEYS_MAX_LENGTH], sTemplate[64]; + GetNativeString(3, SZF(sTemplate)); + + Keys_Generate(SZF(szKey)); + SetNativeString(1, szKey, GetNativeCell(2), true); +} + +// Keys_AddKey(int iClient = 0, const char[] szKey = NULL_STRING, const char[] szKeyType, int iUses, iLifeTime, ArrayList hParamsArr, KeyNativeActionCallback AddKeyCallback, any iData); +public int Native_AddKey(Handle hPlugin, int iNumParams) +{ + int iClient = GetNativeCell(1); + if(iClient && (iClient < 0 || iClient > MaxClients || !IsClientInGame(iClient) || IsFakeClient(iClient))) + { + return 0; + } + + char szKey[KEYS_MAX_LENGTH], szKeyType[KEYS_MAX_LENGTH], szError[PMP]; + GetNativeString(2, SZF(szKey)); + GetNativeString(3, SZF(szKeyType)); + int iUses = GetNativeCell(4); + int iLifeTime = GetNativeCell(5); + ArrayList hParamsArr = view_as(GetNativeCell(6)); + Function fCallback = GetNativeFunction(7); + any iData = GetNativeCell(8); + + szError[0] = 0; + + if(!Keys_Validate(szKey, szKeyType, iUses, iLifeTime, hParamsArr, SZF(szError), iClient)) + { + delete hParamsArr; + API_Callback(Add, hPlugin, fCallback, iClient, szKey, false, szError, iData); + + return 0; + } + + Keys_Add(szKey, szKeyType, iUses, iLifeTime, -1, hParamsArr, iClient, iClient ? SM_REPLY_TO_CHAT:SM_REPLY_TO_CONSOLE, hPlugin, fCallback, iData); + return 0; +} + +//Keys_RemoveKey(int iClient = 0, const char[] szKey, KeyNativeActionCallback RemoveKeyCallback, any iData = 0); +public int Native_RemoveKey(Handle hPlugin, int iNumParams) +{ + int iClient = GetNativeCell(1); + if(iClient && (iClient < 0 || iClient > MaxClients || !IsClientInGame(iClient) || IsFakeClient(iClient))) + { + return 0; + } + + char szKey[KEYS_MAX_LENGTH]; + GetNativeString(2, SZF(szKey)); + + Function fCallback = GetNativeFunction(3); + any iData = GetNativeCell(4); + + Keys_Delete(szKey, true, iClient, iClient ? SM_REPLY_TO_CHAT:SM_REPLY_TO_CONSOLE, hPlugin, fCallback, iData); + return 0; +} + +// Keys_UseKey(int iClient, const char[] szKey, bool bNotify, bool bIgnoreBlock, KeyNativeActionCallback UseKeyCallback, any iData = 0); +public int Native_UseKey(Handle hPlugin, int iNumParams) +{ + int iClient = GetNativeCell(1); + if(iClient < 1 || iClient > MaxClients || !IsClientInGame(iClient) || IsFakeClient(iClient)) + { + return 0; + } + + char szKey[KEYS_MAX_LENGTH]; + GetNativeString(2, SZF(szKey)); + bool bNotify = GetNativeCell(3); + bool bIgnoreBlock = GetNativeCell(4); + + Function fCallback = GetNativeFunction(5); + any iData = GetNativeCell(6); + + if(!bIgnoreBlock && g_bIsBlocked[iClient]) + { + char szError[PMP]; + FormatEx(SZF(szError), "%T%T", "ERROR", iClient, "ERROR_BLOCKED", iClient); + API_Callback(Use, hPlugin, fCallback, iClient, szKey, false, szError, iData); + return 0; + } + + Keys_Use(szKey, iClient, SM_REPLY_TO_CHAT, bNotify, bIgnoreBlock, hPlugin, fCallback, iData); + return 0; +} + +// function void (int iClient, const char[] szKey, bool bSuccess, const char[] szError, any iData); +void API_Callback(KeysNativeAction eKeysAction, Handle hPlugin, Function fCallback, int iClient, const char[] szKey, bool bSuccess = true, const char[] szError = NULL_STRING, any iData) +{ + Call_StartFunction(hPlugin, fCallback); + Call_PushCell(eKeysAction); + Call_PushCell(iClient); + Call_PushString(szKey); + Call_PushCell(bSuccess); + Call_PushString(szError); + Call_PushCell(iData); + Call_Finish(); +} diff --git a/Core/addons/sourcemod/scripting/keys/BLOCK.sp b/Core/addons/sourcemod/scripting/keys/BLOCK.sp new file mode 100644 index 0000000..600440f --- /dev/null +++ b/Core/addons/sourcemod/scripting/keys/BLOCK.sp @@ -0,0 +1,90 @@ + +void Block_ClientDisconnect(int iClient) +{ + g_iAttempts[iClient] = 0; + g_bIsBlocked[iClient] = false; +} + +void Block_ClientConnect(int iClient) +{ + char szQuery[PMP], szAuth[32], szSID[64]; + GetClientAuthId(iClient, AuthId_Engine, SZF(szAuth)); + + if(!g_CVAR_iServerID) + { + szSID[0] = 0; + } + else + { + FormatEx(SZF(szSID), " AND `b_sid` = %d", g_CVAR_iServerID); + } + + FormatEx(SZF(szQuery), "SELECT `b_end` FROM `keys_block_players` WHERE `b_auth` = '%s'%s;", szAuth, szSID); + + g_hDatabase.Query(SQL_Callback_SearchBlockPlayer, szQuery, UID(iClient)); +} + +public void SQL_Callback_SearchBlockPlayer(Database hDB, DBResultSet hResult, const char[] szDbError, any UserID) +{ + if (hResult == null || szDbError[0]) + { + LogError("SQL_Callback_SearchBlockPlayer: %s", szDbError); + return; + } + + int iClient = CID(UserID); + if (iClient) + { + if(hResult.FetchRow()) + { + g_iAttempts[iClient] = hResult.FetchInt(0); + if(g_iAttempts[iClient] && g_iAttempts[iClient] < GetTime()) + { + Block_SetClientStatus(iClient, false); + return; + } + + g_bIsBlocked[iClient] = true; + } + } +} + +void Block_SetClientStatus(int iClient, bool bStatus) +{ + char szQuery[PMP], szAuth[32], szBuffer[64]; + GetClientAuthId(iClient, AuthId_Engine, SZF(szAuth)); + g_bIsBlocked[iClient] = bStatus; + if(bStatus) + { + g_iAttempts[iClient] = GetTime()+(g_CVAR_iBlockTime*60); + GetClientName(iClient, SZF(szBuffer)); + + LogToFile(g_sLogFile, "%T", "LOG_BLOCKED", LANG_SERVER, szBuffer, szAuth); + + if(!g_CVAR_iServerID) + { + FormatEx(SZF(szQuery), "INSERT INTO `keys_block_players` (`b_auth`, `b_end`) VALUES ('%s', %d);", szAuth, g_iAttempts[iClient]); + } + else + { + FormatEx(SZF(szQuery), "INSERT INTO `keys_block_players` (`b_auth`, `b_end`, `b_sid`) VALUES ('%s', %d, %d);", szAuth, g_iAttempts[iClient], g_CVAR_iServerID); + } + } + else + { + g_iAttempts[iClient] = 0; + + if(!g_CVAR_iServerID) + { + szBuffer[0] = 0; + } + else + { + FormatEx(SZF(szBuffer), " AND `b_sid` = %d", g_CVAR_iServerID); + } + + FormatEx(SZF(szQuery), "DELETE FROM `keys_block_players` WHERE `b_auth` = '%s'%s;", szAuth, szBuffer); + } + + g_hDatabase.Query(SQL_Callback_ErrorCheck, szQuery); +} \ No newline at end of file diff --git a/Core/addons/sourcemod/scripting/keys/CMD.sp b/Core/addons/sourcemod/scripting/keys/CMD.sp new file mode 100644 index 0000000..4d02d11 --- /dev/null +++ b/Core/addons/sourcemod/scripting/keys/CMD.sp @@ -0,0 +1,491 @@ + +void CMD_Reg() +{ + // CMD`s for use keys + RegConsoleCmd("key", UseKey_CMD); + RegConsoleCmd("usekey", UseKey_CMD); + + // CMD`s for create keys + RegAdminCmd("key_add", AddKey_CMD, ADMFLAG_ROOT); + RegAdminCmd("key_create", AddKey_CMD, ADMFLAG_ROOT); + RegAdminCmd("keys_gen", AddKey_CMD, ADMFLAG_ROOT); + + // CMD`s for remove keys + RegAdminCmd("key_del", DelKey_CMD, ADMFLAG_ROOT); + RegAdminCmd("key_rem", DelKey_CMD, ADMFLAG_ROOT); + RegAdminCmd("keys_clear", ClearKeys_CMD, ADMFLAG_ROOT); + + // CMD`s for keys output +// RegAdminCmd("keys_list", KeysListDump_CMD, ADMFLAG_ROOT); +// RegAdminCmd("keys_dump", KeysListDump_CMD, ADMFLAG_ROOT); +} + +public Action UseKey_CMD(int iClient, int iArgs) +{ + if (iClient) + { + ReplySource CmdReplySource = GetCmdReplySource(); + + if(g_CVAR_iAttempts && g_bIsBlocked[iClient]) + { + if(g_iAttempts[iClient] > GetTime()) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_BLOCKED"); + return Plugin_Handled; + + } + else + { + Block_SetClientStatus(iClient, false); + } + } + + if(iArgs != 1) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "USAGE_ERROR_USE_KEY"); + return Plugin_Handled; + } + + char szKey[KEYS_MAX_LENGTH], szQuery[PMP*2]; + GetCmdArg(1, SZF(szKey)); + + if(!Keys_Check(szKey, SZF(szQuery))) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", szQuery); + + if(g_CVAR_iAttempts) + { + if(g_iAttempts[iClient]++ >= g_CVAR_iAttempts) + { + Block_SetClientStatus(iClient, true); + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_BLOCKED"); + return Plugin_Handled; + } + + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_KEY_LEFT", g_CVAR_iAttempts-g_iAttempts[iClient]); + } + else + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_KEY"); + } + + return Plugin_Handled; + } + + Keys_Use(szKey, iClient, CmdReplySource, true, false); + } + + return Plugin_Handled; +} + +public Action AddKey_CMD(int iClient, int iArgs) +{ + ReplySource CmdReplySource = GetCmdReplySource(); + + if(iArgs < 5) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_NUM_ARGS"); + return Plugin_Handled; + } + + char szKey[KEYS_MAX_LENGTH]; + + GetCmdArg(0, SZF(szKey)); + + bool bGen = (szKey[3] == 's'); + + int iCount; + if(bGen) + { + GetCmdArg(1, SZF(szKey)); + iCount = S2I(szKey); + if(iCount < 1) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_AMOUNT"); + return Plugin_Handled; + } + + szKey[0] = 0; + } + else + { + GetCmdArg(1, SZF(szKey)); + } + + char szKeyType[KEYS_MAX_LENGTH], szParam[KEYS_MAX_LENGTH], szError[PMP]; + GetCmdArg(4, SZF(szKeyType)); + + GetCmdArg(2, SZF(szParam)); + int iLifeTime = S2I(szParam); + + GetCmdArg(3, SZF(szParam)); + int iUses = S2I(szParam); + + ArrayList hParamsArr = new ArrayList(ByteCountToCells(KEYS_MAX_LENGTH)); + + for(int i = 5; i <= iArgs; ++i) + { + GetCmdArg(i, SZF(szParam)); + hParamsArr.PushString(szParam); + } + + szError[0] = 0; + + if(!bGen && !Keys_Validate(szKey, szKeyType, iUses, iLifeTime, hParamsArr, SZF(szError), iClient)) + { + delete hParamsArr; + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%s", "ERROR", szError); + return Plugin_Handled; + } + + int iExpires = iLifeTime ? (iLifeTime + GetTime()):iLifeTime; + if(bGen) + { + szKey = NULL_STRING; + LogMessage("LOOP: %d", iCount); + while(iCount > 0) + { + --iCount; + LogMessage("LOOP ITER: %d", iCount); + + Keys_Add(szKey, szKeyType, iUses, iLifeTime, iExpires, hParamsArr.Clone(), iClient, CmdReplySource); + } + } + else + { + Keys_Add(szKey, szKeyType, iUses, iLifeTime, iExpires, hParamsArr.Clone(), iClient, CmdReplySource); + } + + delete hParamsArr; + + return Plugin_Handled; +} + +public Action DelKey_CMD(int iClient, int iArgs) +{ + ReplySource CmdReplySource = GetCmdReplySource(); + + if(iArgs != 1) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_NUM_ARGS"); + return Plugin_Handled; + } + + char szKey[KEYS_MAX_LENGTH], iLength; + GetCmdArg(1, SZF(szKey)); + + iLength = strlen(szKey); + if(iLength > KEYS_MAX_LENGTH || iLength < 8) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_KEY"); + return Plugin_Handled; + } + + Keys_Delete(szKey, true, iClient, CmdReplySource); + + return Plugin_Handled; +} + +public Action ClearKeys_CMD(int iClient, int iArgs) +{ + ReplySource CmdReplySource = GetCmdReplySource(); + + char szKeyType[64]; + if(iArgs == 1) + { + GetCmdArg(1, SZF(szKeyType)); + if(FindStringInArray(g_hKeysArray, szKeyType) == -1) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_TYPE"); + return Plugin_Handled; + } + } + else + { + szKeyType[0] = 0; + } + + char szQuery[PMP], szSID[64]; + DataPack hDP = new DataPack(); + hDP.WriteCell(GET_UID(iClient)); + hDP.WriteCell(CmdReplySource); + if(szKeyType[0]) + { + if(!g_CVAR_iServerID) + { + szSID[0] = 0; + } + else + { + FormatEx(SZF(szSID), " AND `k_sid` = %d", g_CVAR_iServerID); + } + + FormatEx(SZF(szQuery), "DELETE FROM `keys_tokens` WHERE `k_type` = '%s'%s;", szKeyType, szSID); + + hDP.WriteCell(true); + hDP.WriteString(szKeyType); + } + else + { + if(!g_CVAR_iServerID) + { + szSID[0] = 0; + } + else + { + FormatEx(SZF(szSID), " WHERE `k_sid` = %d;", g_CVAR_iServerID); + } + + FormatEx(SZF(szQuery), "DELETE FROM `keys_tokens`%s;", szSID); + } + + g_hDatabase.Query(SQL_Callback_RemoveKeys, szQuery, hDP); + + return Plugin_Handled; +} + +public void SQL_Callback_RemoveKeys(Database hDB, DBResultSet hResult, const char[] szDbError, any hCbDP) +{ + DataPack hDP = view_as(hCbDP); + + if (hResult == null || szDbError[0]) + { + delete hDP; + LogError("SQL_Callback_RemoveKeys: %s", szDbError); + return; + } + + hDP.Reset(); + + int iClient = GET_CID(hDP.ReadCell()); + ReplySource CmdReplySource = view_as(hDP.ReadCell()); + + char szKeyType[64], szName[MAX_NAME_LENGTH], szAuth[32]; + + CmdReplySource = view_as(hDP.ReadCell()); + + if(iClient == -1) + { + iClient = 0; + } + + if(!iClient) + { + strcopy(SZF(szName), "CONSOLE"); + strcopy(SZF(szAuth), "STEAM_ID_SERVER"); + } + else + { + GetClientName(iClient, SZF(szName)); + GetClientAuthId(iClient, AuthId_Engine, SZF(szAuth)); + } + + if(hDP.ReadCell()) + { + hDP.ReadString(SZF(szKeyType)); + } + else + { + szKeyType[0] = 0; + } + + delete hDP; + + if(hResult.AffectedRows) + { + if(szKeyType[0]) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", "SUCCESS_REMOVE_KEYS_TYPE", szKeyType); + LogToFile(g_sLogFile, "%T", "LOG_SUCCESS_REMOVE_KEYS_TYPE", LANG_SERVER, szKeyType, szName, szAuth); + } + else + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", "SUCCESS_REMOVE_KEYS"); + LogToFile(g_sLogFile, "%T", "LOG_SUCCESS_REMOVE_KEYS", LANG_SERVER, szKeyType, szName, szAuth); + } + } + else + { + if(szKeyType[0]) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_REMOVE_KEYS_TYPE", szKeyType); + LogToFile(g_sLogFile, "%T", "LOG_ERROR_REMOVE_KEYS_TYPE", LANG_SERVER, szKeyType, szName, szAuth); + } + else + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_REMOVE_KEYS"); + LogToFile(g_sLogFile, "%T", "LOG_ERROR_REMOVE_KEYS", LANG_SERVER, szKeyType, szName, szAuth); + } + } +} +/* +public Action KeysListDump_CMD(int iClient, int iArgs) +{ + char szQuery[PMP*2], szSID[64]; + ReplySource CmdReplySource = GetCmdReplySource(); + + int iOffset = 0; + if(iArgs) + { + GetCmdArg(2, szQuery, 16); + iOffset = StringToInt(szQuery); + if(iOffset < 0) + { + iOffset = 0; + } + } + + DataPack hDP = new DataPack(); + hDP.WriteCell(GET_UID(iClient)); + hDP.WriteCell(CmdReplySource); + GetCmdArg(0, szQuery, 32); + bool bToFile = szQuery[5] == 'd'; + hDP.WriteCell(bToFile); + + if(!g_CVAR_iServerID) + { + szSID[0] = 0; + } + else + { + FormatEx(SZF(szSID), " WHERE `k_sid` = %d;", g_CVAR_iServerID); + } + + if(!g_iServerID) + { + FormatEx(SZF(szQuery), "SELECT `k_name`, `k_type`, `k_expires`, `k_uses`, `param1`, `param2`, `param3`, `param4`, `param5` FROM `keys_tokens` ORDER BY `k_type`, `param1`, `param2`, `param3`, `param4`, `param5`, `k_expires`, `k_uses`;"); + } + else + { + FormatEx(SZF(szQuery), "SELECT `k_name`, `k_type`, `k_expires`, `k_uses`, `param1`, `param2`, `param3`, `param4`, `param5` FROM `keys_tokens` WHERE `k_sid` = %d ORDER BY `k_type`, `param1`, `param2`, `param3`, `param4`, `param5`, `k_expires`, `k_uses`;", g_iServerID); + } + + if(!bToFile) + { + szQuery[strlen(szQuery)-1] = 0; + Format(SZF(szQuery), "%s LIMIT %d, %d;", szQuery, iOffset, iClient ? 20:100); + } + + g_hDatabase.Query(SQL_Callback_SelectKeysList, szQuery, hDP); + + return Plugin_Handled; +} + +public void SQL_Callback_SelectKeysList(Database hDB, DBResultSet hResult, const char[] szDbError, any hCbDP) +{ + if (hResult == null || szDbError[0]) + { + delete hDP; + LogError("SQL_Callback_SelectKeysList: %s", szDbError); + return; + } + + hDP.Reset(); + decl iClient, ReplySource:CmdReplySource, bool:bToFile; + iClient = GET_CID(hDP.ReadCell()); + CmdReplySource = view_as(hDP.ReadCell()); + bToFile = view_as(hDP.ReadCell()); + delete hDP; + + if(!bToFile && iClient == -1) + { + return; + } + + if(SQL_GetRowCount(hResult) > 0) + { + char szKey[64], szKeyType[64], sExpires[64], iUses, iCount, iTime, iExpires, i; + decl Handle:hFile, Handle:hDataPack, Handle:hPlugin, Function:fPrintCallback, ArrayList hParamsArr, szParam[KEYS_MAX_LENGTH], sParams[PMP*2]; + + if(bToFile) + { + BuildPath(Path_SM, SZF(sParams), "data/keys_dump.txt"); + hFile = OpenFile(sParams, "w+"); + } + + iCount = 0; + iTime = GetTime(); + + while(hResult.FetchRow()) + { + hResult.FetchString(1, SZF(szKeyType)); + + if(g_hKeysTrie.GetValue(szKeyType, hDataPack)) + { + hResult.FetchString(0, SZF(szKey)); + + iExpires = hResult.FetchInt(2); + + if(iExpires) + { + if(iExpires < iTime) + { + Keys_Delete(szKey); + continue; + } + + Keys_GetTimeFromStamp(SZF(sExpires), iExpires-iTime, iClient); + } + else + { + FormatEx(SZF(sExpires), "%T", "FOREVER", iClient); + } + + iUses = hResult.FetchInt(3); + + if(!iUses) + { + Keys_Delete(szKey); + continue; + } + + hParamsArr = CreateArray(ByteCountToCells(KEYS_MAX_LENGTH)); + + for(i = 4; i < 9; ++i) + { + if(SQL_IsFieldNull(hResult, i)) + { + break; + } + + hResult.FetchString(i, SZF(szParam)); + PushArrayString(hParamsArr, szParam); + } + + sParams[0] = 0; + + hDataPack.Position = DP_Plugin; + hPlugin = view_as(hDataPack.ReadCell()); + hDataPack.Position = DP_OnPrintCallback; + fPrintCallback = hDataPack.ReadFunction(); + Call_StartFunction(hPlugin, fPrintCallback); + Call_PushCell(iClient); + Call_PushString(szKeyType); + Call_PushCell(hParamsArr); + Call_PushStringEx(sParams, 256, SM_PARAM_STRING_UTF8|SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); + Call_PushCell(256); + Call_Finish(); + + delete hParamsArr; + + if(bToFile) + { + WriteFileLine(hFile, "%d. %s\t\t%T: %12s\t\t%T: %4i\t\t%T: %s\t\t%s", ++iCount, szKey, "EXPIRES", iClient, sExpires, "USAGE_LEFT", iClient, iUses, "TYPE", iClient, szKeyType, sParams); + continue; + } + + UTIL_ReplyToCommand(iClient, CmdReplySource, "%d. %s\t\t%T: %12s\t\t%T: %4i\t\t%T: %s\t\t%s", ++iCount, szKey, "EXPIRES", iClient, sExpires, "USAGE_LEFT", iClient, iUses, "TYPE", iClient, szKeyType, sParams); + } + } + + if(bToFile) + { + delete hFile; + } + } + else + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_LIST_NO_KEYS"); + } +} +*/ \ No newline at end of file diff --git a/Core/addons/sourcemod/scripting/keys/EVENTS.sp b/Core/addons/sourcemod/scripting/keys/EVENTS.sp new file mode 100644 index 0000000..a0e0643 --- /dev/null +++ b/Core/addons/sourcemod/scripting/keys/EVENTS.sp @@ -0,0 +1,36 @@ + +public void OnMapStart() +{ + Stats_OnMapStart(); +} + +public void OnConfigsExecuted() +{ + if(g_bIsStarted) + { + Keys_DeleteExpired(); + } +} + +public Action OnClientSayCommand(int iClient, const char[] sCommand, const char[] sArgs) +{ + if(StrContains(sArgs, "key") != -1) + { + return Plugin_Handled; + } + + return Plugin_Continue; +} + +public void OnClientDisconnect(int iClient) +{ + Block_ClientDisconnect(iClient); +} + +public void OnClientPostAdminCheck(int iClient) +{ + if(!IsFakeClient(iClient)) + { + Block_ClientConnect(iClient); + } +} \ No newline at end of file diff --git a/Core/addons/sourcemod/scripting/keys/KEYS.sp b/Core/addons/sourcemod/scripting/keys/KEYS.sp new file mode 100644 index 0000000..af4cb5a --- /dev/null +++ b/Core/addons/sourcemod/scripting/keys/KEYS.sp @@ -0,0 +1,1006 @@ + +void Keys_DeleteExpired() +{ + char szQuery[PMP], szSID[64]; + + if(!g_CVAR_iServerID) + { + szSID[0] = 0; + } + else + { + FormatEx(SZF(szSID), " AND `k_sid` = %d", g_CVAR_iServerID); + } + + FormatEx(SZF(szQuery), "DELETE FROM `keys_tokens` WHERE `k_expires` > 0 AND `k_expires` < %d%s;", GetTime(), szSID); + + g_hDatabase.Query(SQL_Callback_ErrorCheck, szQuery); +} + +bool Keys_Check(const char[] szKey, char[] szError, int iErrLen) +{ + if(!szKey[0]) + { + strcopy(szError, iErrLen, "ERROR_KEY_EMPTY"); + return false; + } + + int iLength = strlen(szKey); + if(iLength < 8) + { + strcopy(szError, iErrLen, "ERROR_KEY_SHORT"); + return false; + } + + if(iLength > 64) + { + strcopy(szError, iErrLen, "ERROR_KEY_LONG"); + return false; + } + + int i = 0; + + while (i < iLength) + { + if((szKey[i] > 0x2F && szKey[i] < 0x3A) || + (szKey[i] > 0x40 && szKey[i] < 0x5B) || + (szKey[i] > 0x60 && szKey[i] < 0x7B) || + szKey[i] == 0x2D) + { + ++i; + continue; + } + + strcopy(szError, iErrLen, "ERROR_KEY_INVALID_CHARACTERS"); + return false; + } + + return true; +} + +void Keys_Generate(char[] szKey, int iMaxLen) +{ + szKey[0] = '\0'; + + int i = 0; + + if(g_CVAR_sKeyTemplate[0]) + { + int iLength = strlen(g_CVAR_sKeyTemplate); + while (i < iLength && i < iMaxLen) + { + szKey[i] = view_as(UTIL_GetCharTemplate(g_CVAR_sKeyTemplate[i])); + ++i; + } + } + else + { + while (i < g_CVAR_iKeyLength && i < iMaxLen) + { + szKey[i] = view_as(UTIL_GetCharTemplate(0x58)); + ++i; + } + } + + szKey[i] = '\0'; +} + +bool Keys_Validate(char[] szKey, const char[] szKeyType, int iUses, int iLifeTime, ArrayList hParamsArr, char[] szError, int iErrLen, int iClient = LANG_SERVER) +{ + DataPack hDataPack; + + if(!g_hKeysTrie.GetValue(szKeyType, hDataPack)) + { + FormatEx(szError, iErrLen, "%T%T", "ERROR", iClient, "ERROR_INCORRECT_TYPE", iClient); + return false; + } + + if(szKey[0]) + { + if(!Keys_Check(szKey, szError, iErrLen)) + { + return false; + } + } + + if(iLifeTime < 0) + { + FormatEx(szError, iErrLen, "%T%T", "ERROR", iClient, "ERROR_INCORRECT_LIFETIME", iClient); + return false; + } + + if(iUses < 1) + { + FormatEx(szError, iErrLen, "%T%T", "ERROR", iClient, "ERROR_INCORRECT_USES", iClient); + return false; + } + + hDataPack.Reset(); + Handle hPlugin = view_as(hDataPack.ReadCell()); + Function fCallback = hDataPack.ReadFunction(); + + strcopy(szError, iErrLen, "unknown"); + bool bResult = false; + Call_StartFunction(hPlugin, fCallback); + Call_PushCell(Validation); + Call_PushCell(iClient); + Call_PushString(szKeyType); + Call_PushCell(hParamsArr); + Call_PushStringEx(szError, iErrLen, SM_PARAM_STRING_UTF8|SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); + Call_PushCell(iErrLen); + Call_Finish(bResult); + + if(!bResult) + { + FormatEx(szError, iErrLen, "%T%s", "ERROR", iClient, szError); + return false; + } + + return true; +} + +/* +************************************************************************************************************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +********************************************************* ****************************************************** +********************************************************* ****************************************************** +********************************************************* С О З Д А Н И Е ****************************************************** +********************************************************* ****************************************************** +********************************************************* ****************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +*/ + +void Keys_Add(char[] szKeySource = NULL_STRING, + const char[] szKeyType, + int iUses, + int iLifeTime, + int iExpires = -1, + ArrayList hParamsArr, + int iClient, + ReplySource CmdReplySource, + Handle hPlugin = null, + Function fCallback = INVALID_FUNCTION, + any iData = 0) +{ + LogMessage("Keys_Add: '%s', '%s'", szKeySource, szKeyType); + + DataPack hDP = new DataPack(); + hDP.WriteCell(hParamsArr); + char szKey[KEYS_MAX_LENGTH]; + if(szKey[0]) + { + strcopy(SZF(szKey), szKeySource); + hDP.WriteString(szKey); + hDP.WriteCell(true); + } + else + { + Keys_Generate(szKey, KEYS_MAX_LENGTH); + LogMessage("Keys_Generate: '%s'", szKey); + + hDP.WriteString(szKey); + hDP.WriteCell(false); + } + + hDP.WriteCell(GET_UID(iClient)); + hDP.WriteCell(CmdReplySource); + hDP.WriteString(szKeyType); + hDP.WriteCell(iUses); + hDP.WriteCell(iLifeTime); + if(iExpires == -1) + { + iExpires = iLifeTime ? (iLifeTime + GetTime()):iLifeTime; + } + hDP.WriteCell(iExpires); + + if(hPlugin != null && fCallback != INVALID_FUNCTION) + { + hDP.WriteCell(true); + hDP.WriteCell(hPlugin); + hDP.WriteFunction(fCallback); + hDP.WriteCell(iData); + } + else + { + hDP.WriteCell(false); + } + + char szQuery[PMP], szSID[64]; + + if(!g_CVAR_iServerID) + { + szSID[0] = 0; + } + else + { + FormatEx(SZF(szSID), " AND `k_sid` = %d", g_CVAR_iServerID); + } + + FormatEx(SZF(szQuery), "SELECT `k_expires`, `k_uses` FROM `keys_tokens` WHERE `k_name` = '%s'%s;", szKey, szSID); + g_hDatabase.Query(SQL_Callback_SearchKey, szQuery, hDP); +} + +public void SQL_Callback_SearchKey(Database hDB, DBResultSet hResult, const char[] szDbError, any hCbDP) +{ + DataPack hDP = view_as(hCbDP); + hDP.Reset(); + ArrayList hParamsArr = view_as(hDP.ReadCell()); + + if (hResult == null || szDbError[0]) + { + LogError("SQL_Callback_SearchKey: %s", szDbError); + delete hParamsArr; + delete hDP; + return; + } + + char szQuery[1024], szKey[KEYS_MAX_LENGTH]; + int i; + hDP.ReadString(SZF(szKey)); + + if(hResult.FetchRow()) // Ключ уже есть в базе + { + i = hResult.FetchInt(0); + if(!i || i > GetTime()) + { + i = hResult.FetchInt(1); + if(i) + { + if(hDP.ReadCell()) // Отправить ошибку о сущевствующем ключе + { + i = GET_CID(hDP.ReadCell()); + if(i != -1) + { + UTIL_ReplyToCommand(i, view_as(hDP.ReadCell()), "%t%t", "ERROR", "ERROR_KEY_ALREADY_EXISTS", szKey); + } + else + { + hDP.ReadCell(); // CmdReplySource + } + + hDP.ReadString(szQuery, KEYS_MAX_LENGTH); // KeyType + // hDP.Position = hDP.Position + view_as(27); + hDP.ReadCell(); + hDP.ReadCell(); + hDP.ReadCell(); + + if(hDP.ReadCell()) // hDP.ReadCell() + { + FormatEx(szQuery, 256, "%T%T", "ERROR", LANG_SERVER, "ERROR_KEY_ALREADY_EXISTS", LANG_SERVER, szKey); + Handle hPlugin = view_as(hDP.ReadCell()); + Function fCallback = hDP.ReadFunction(); + any iData = hDP.ReadCell(); + API_Callback(Add, hPlugin, fCallback, i, szKey, false, szQuery, iData); + } + + delete hParamsArr; + delete hDP; + return; + } + else // Сгенерировать новый ключ + { + i = hDP.ReadCell(); + ReplySource CmdReplySource = view_as(hDP.ReadCell()); + //char szKeyType[KEYS_MAX_LENGTH]; + hDP.ReadString(szQuery, KEYS_MAX_LENGTH); // KeyType + + int iUses = hDP.ReadCell(); + int iLifeTime = hDP.ReadCell(); + int iExpires = hDP.ReadCell(); + + if(hDP.ReadCell()) // hDP.ReadCell() + { + Handle hPlugin = view_as(hDP.ReadCell()); + Function fCallback = hDP.ReadFunction(); + any iData = hDP.ReadCell(); + Keys_Add("", szQuery, iUses, iLifeTime, iExpires, hParamsArr, i, CmdReplySource, hPlugin, fCallback, iData); + } + else + { + Keys_Add(szKey, szQuery, iUses, iLifeTime, iExpires, hParamsArr, i, CmdReplySource); + } + + delete hDP; + } + + return; + } + } + + Keys_Delete(szKey); + } + + hDP.ReadCell(); // bDuplicateErr + hDP.ReadCell(); // Client + hDP.ReadCell(); // CmdReplySource + + char szKeyType[KEYS_MAX_LENGTH]; + + hDP.ReadString(SZF(szKeyType)); + + int iUses = hDP.ReadCell(); + hDP.ReadCell(); // iLifeTime + int iExpires = hDP.ReadCell(); + + if(!g_CVAR_iServerID) + { + FormatEx(SZF(szQuery), "INSERT INTO `keys_tokens` (`k_name`, `k_type`, `k_expires`, `k_uses`) VALUES ('%s', '%s', %d, %d);", szKey, szKeyType, iExpires, iUses); + } + else + { + FormatEx(SZF(szQuery), "INSERT INTO `keys_tokens` (`k_name`, `k_type`, `k_expires`, `k_uses`, `k_sid`) VALUES ('%s', '%s', %d, %d, %d);", szKey, szKeyType, iExpires, iUses, g_CVAR_iServerID); + } + LogMessage(szQuery); + g_hDatabase.Query(SQL_Callback_AddKey, szQuery, hDP); +} + +public void SQL_Callback_AddKey(Database hDB, DBResultSet hResult, const char[] szDbError, any hCbDP) +{ + DataPack hDP = view_as(hCbDP); + hDP.Reset(); + ArrayList hParamsArr = view_as(hDP.ReadCell()); + + if (hResult == null || szDbError[0]) + { + LogError("SQL_Callback_AddKey: %s", szDbError); + delete hParamsArr; + delete hDP; + return; + } + + int iKeyID = hResult.InsertId; + + char szQuery[PMP*2], sParams[KEYS_MAX_LENGTH]; + Transaction hTxn = new Transaction(); + for(int i = 0; i < hParamsArr.Length; ++i) + { + hParamsArr.GetString(i, SZF(sParams)); + FormatEx(SZF(szQuery), "INSERT INTO `keys_params` (`p_kid`, `p_num`, `p_value`) VALUES (%d, %d, '%s');", iKeyID, i+1, sParams); + hTxn.AddQuery(szQuery); + } + + SQL_FastQuery(g_hDatabase, "SET CHARSET 'utf8'"); + + g_hDatabase.Execute(hTxn, SQL_Callback_AddParamsSuccess, SQL_Callback_AddParamsFailure, hDP); +} + +public void SQL_Callback_AddParamsFailure(Database hDB, any hDataPack, int iNumQueries, const char[] szError, int iFailIndex, any[] queryData) +{ + DataPack hDP = view_as(hDataPack); + hDP.Reset(); + ArrayList hParamsArr = view_as(hDP.ReadCell()); + + delete hParamsArr; + delete hDP; + + LogError("Не удалось добавить параметры (%d): %s", iFailIndex, szError); +} + +public void SQL_Callback_AddParamsSuccess(Database hDB, any hData, int iNumQueries, DBResultSet[] hResults, any[] queryData) +{ + DataPack hDP = view_as(hData); + hDP.Reset(); + ArrayList hParamsArr = view_as(hDP.ReadCell()); + + char szKey[KEYS_MAX_LENGTH], szKeyType[KEYS_MAX_LENGTH], sParams[PMP*2], szName[MAX_NAME_LENGTH], szAuth[32], sExpires[64]; + int iUses, iLifeTime, iClient, iLangClient; + hDP.ReadString(SZF(szKey)); + hDP.ReadCell(); + iClient = GET_CID(hDP.ReadCell()); + ReplySource CmdReplySource = view_as(hDP.ReadCell()); + hDP.ReadString(SZF(szKeyType)); + + iUses = hDP.ReadCell(); + iLifeTime = hDP.ReadCell(); + hDP.ReadCell(); + + Handle hPlugin; + Function fCallback; + + if(hDP.ReadCell()) + { + hPlugin = view_as(hDP.ReadCell()); + fCallback = hDP.ReadFunction(); + any iData = hDP.ReadCell(); + API_Callback(Add, hPlugin, fCallback, iClient, szKey, true, NULL_STRING, iData); + } + + if(iClient > 0) + { + GetClientName(iClient, SZF(szName)); + GetClientAuthId(iClient, AuthId_Engine, SZF(szAuth)); + iLangClient = iClient; + } + else + { + iLangClient = LANG_SERVER; + + strcopy(SZF(szName), "CONSOLE"); + strcopy(SZF(szAuth), "STEAM_ID_SERVER"); + } + + if(iLifeTime) + { + Keys_GetTimeFromStamp(SZF(sExpires), iLifeTime, iLangClient); + } + else + { + FormatEx(SZF(sExpires), "%T", "FOREVER", iLangClient); + } + + sParams[0] = 0; + + DataPack hDataPack; + g_hKeysTrie.GetValue(szKeyType, hDataPack); + hDataPack.Reset(); + hPlugin = view_as(hDataPack.ReadCell()); + fCallback = hDataPack.ReadFunction(); + Call_StartFunction(hPlugin, fCallback); + Call_PushCell(Print); + Call_PushCell(LANG_SERVER); + Call_PushString(szKeyType); + Call_PushCell(hParamsArr); + Call_PushStringEx(SZF(sParams), SM_PARAM_STRING_UTF8|SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); + Call_PushCell(sizeof(sParams)); + Call_Finish(); + + if(hResults[0].AffectedRows) + { + if(iClient != -1) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", "SUCCESS_CREATE_KEY", szKey); + } + + LogToFile(g_sLogFile, "%T", "LOG_SUCCESS_CREATE_KEY", LANG_SERVER, szName, szAuth, szKey, sExpires, iUses, szKeyType, sParams); + } + else + { + if(iClient != -1) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_CREATE_KEY", szKey); + } + + LogToFile(g_sLogFile, "%T", "LOG_ERROR_CREATE_KEY", LANG_SERVER, szKey, szName, szAuth, sExpires, iUses, szKeyType, sParams); + } + + delete hParamsArr; + delete hDP; +} + +/* +************************************************************************************************************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +********************************************************* ****************************************************** +********************************************************* ****************************************************** +********************************************************* У Д А Л Е Н И Е ****************************************************** +********************************************************* ****************************************************** +********************************************************* ****************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +*/ + +void Keys_Delete(const char[] szKey, + bool bSearch = false, + int iClient = -1, + ReplySource CmdReplySource = SM_REPLY_TO_CONSOLE, + Handle hPlugin = null, + Function fCallback = INVALID_FUNCTION, + any iData = 0) +{ + DataPack hDP = new DataPack(); + hDP.WriteString(szKey); + hDP.WriteCell((iClient != -1)); + hDP.WriteCell(GET_UID(iClient)); + hDP.WriteCell(CmdReplySource); + + if(hPlugin != null && fCallback != INVALID_FUNCTION) + { + hDP.WriteCell(true); + hDP.WriteCell(hPlugin); + hDP.WriteFunction(fCallback); + hDP.WriteCell(iData); + } + else + { + hDP.WriteCell(false); + } + + char szQuery[PMP*2], szSID[64]; + + if(!g_CVAR_iServerID) + { + szSID[0] = 0; + } + else + { + FormatEx(SZF(szSID), " AND `k_sid` = %d", g_CVAR_iServerID); + } + + if(bSearch) + { + FormatEx(SZF(szQuery), "SELECT `k_id` FROM `keys_tokens` WHERE `k_name` = '%s'%s;", szKey, szSID); + g_hDatabase.Query(SQL_Callback_SearchDelKey, szQuery, hDP); + } + else + { + // DELETE FROM `keys_params` WHERE `p_kid` = IFNULL((SELECT `k_id` FROM `keys_tokens` WHERE `k_name` = '%s'), 0); + // DELETE FROM `keys_tokens` WHERE `k_name` = '%s'; + // DELETE FROM `keys_params` WHERE `p_kid` = IFNULL((SELECT `k_id` FROM `keys_tokens` WHERE `k_name` = '%s' AND `k_sid` = %d), 0); + // DELETE FROM `keys_tokens` WHERE `k_name` = '%s' AND `k_sid` = %d; + + FormatEx(SZF(szQuery), "DELETE FROM `keys_params` WHERE `p_kid` = IFNULL((SELECT `k_id` FROM `keys_tokens` WHERE `k_name` = '%s'%s), 0); \ + DELETE FROM `keys_tokens` WHERE `k_name` = '%s'%s;", szKey, szSID, szKey, szSID); + + g_hDatabase.Query(SQL_Callback_RemoveKey, szQuery, hDP); + } +} + +public void SQL_Callback_SearchDelKey(Database hDB, DBResultSet hResult, const char[] szDbError, any hCbDP) +{ + DataPack hDP = view_as(hCbDP); + + if (hResult == null || szDbError[0]) + { + delete hDP; + LogError("SQL_Callback_SearchDelKey: %s", szDbError); + return; + } + + if(hResult.FetchRow()) + { + int iKeyID = hResult.FetchInt(0); + + char szQuery[PMP*2]; + + FormatEx(SZF(szQuery), "DELETE FROM `keys_params` WHERE `p_kid` = %d; \ + DELETE FROM `keys_tokens` WHERE `k_id` = %d;", iKeyID, iKeyID); + + g_hDatabase.Query(SQL_Callback_RemoveKey, szQuery, hDP); + return; + } + + Keys_NotifyDelResult(hDP, false); +} + +public void SQL_Callback_RemoveKey(Database hDB, DBResultSet hResult, const char[] szDbError, any hCbDP) +{ + DataPack hDP = view_as(hCbDP); + + if (hResult == null || szDbError[0]) + { + delete hDP; + LogError("SQL_Callback_RemoveKey: %s", szDbError); + return; + } + + Keys_NotifyDelResult(hDP, hResult.AffectedRows != 0); +} + +void Keys_NotifyDelResult(DataPack hDP, bool bResult) +{ + hDP.Reset(); + + char szKey[KEYS_MAX_LENGTH]; + hDP.ReadString(SZF(szKey)); + + bool bReply = hDP.ReadCell(); + + int iClient = GET_CID(hDP.ReadCell()); + + if(iClient == -1) + { + iClient = 0; + } + + ReplySource CmdReplySource = view_as(hDP.ReadCell()); + + char szName[MAX_NAME_LENGTH], szAuth[32]; + if(!iClient) + { + strcopy(SZF(szName), "CONSOLE"); + strcopy(SZF(szAuth), "STEAM_ID_SERVER"); + } + else + { + GetClientName(iClient, SZF(szName)); + GetClientAuthId(iClient, AuthId_Engine, SZF(szAuth)); + } + + if(bReply) + { + if(bResult) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", "SUCCESS_REMOVE_KEY", szKey); + + LogToFile(g_sLogFile, "%T", "LOG_SUCCESS_REMOVE_KEY", LANG_SERVER, szKey, szName, szAuth); + } + else + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_REMOVE_KEY", szKey); + + LogToFile(g_sLogFile, "%T", "LOG_ERROR_REMOVE_KEY", LANG_SERVER, szKey, szName, szAuth); + } + } + + if(hDP.ReadCell()) + { + Handle hPlugin = view_as(hDP.ReadCell()); + Function fCallback = hDP.ReadFunction(); + any iData = hDP.ReadCell(); + if(bResult) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", "SUCCESS_REMOVE_KEY", szKey); + + LogToFile(g_sLogFile, "%T", "LOG_SUCCESS_REMOVE_KEY", LANG_SERVER, szKey, szName, szAuth); + API_Callback(Rem, hPlugin, fCallback, iClient, szKey, true, NULL_STRING, iData); + } + else + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", "SUCCESS_REMOVE_KEY", szKey); + + LogToFile(g_sLogFile, "%T", "LOG_ERROR_REMOVE_KEY", LANG_SERVER, szKey, szName, szAuth); + API_Callback(Rem, hPlugin, fCallback, iClient, szKey, false, "Keys don't search", iData); + } + } + + delete hDP; +} + +/* +************************************************************************************************************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +********************************************************* ****************************************************** +********************************************************* ****************************************************** +********************************************************* И С П О Л Ь З О В А Н И Е ****************************************************** +********************************************************* ****************************************************** +********************************************************* ****************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +************************************************************************************************************************************************** +*/ + +void Keys_Use(const char[] szKey, + int iClient, + ReplySource CmdReplySource = SM_REPLY_TO_CHAT, + bool bNotify, + bool bIgnoreBlock, + Handle hPlugin = null, + Function fCallback = INVALID_FUNCTION, + any iData = 0) +{ + DataPack hDP = new DataPack(); + hDP.WriteString(szKey); + hDP.WriteCell(UID(iClient)); + hDP.WriteCell(CmdReplySource); + hDP.WriteCell(bNotify); + + if(hPlugin != null && fCallback != INVALID_FUNCTION) + { + hDP.WriteCell(true); + hDP.WriteCell(hPlugin); + hDP.WriteFunction(fCallback); + hDP.WriteCell(iData); + } + else + { + hDP.WriteCell(false); + } + + char szQuery[PMP*2], szAuth[32]; + GetClientAuthId(iClient, AuthId_Engine, SZF(szAuth)); + + char szSID[64]; + + if(!g_CVAR_iServerID) + { + szSID[0] = 0; + } + else + { + FormatEx(SZF(szSID), " AND `k_sid` = %d", g_CVAR_iServerID); + } + + FormatEx(SZF(szQuery), "SELECT `k_id`, `k_type`, `k_expires`, `k_uses` FROM `keys_tokens` WHERE `k_name` = '%s'%s LIMIT 1;", szKey, szSID); + + g_hDatabase.Query(SQL_Callback_SelectUseKey, szQuery, hDP); +} + +public void SQL_Callback_SelectUseKey(Database hDB, DBResultSet hResult, const char[] szDbError, any hCbDP) +{ + DataPack hDP = view_as(hCbDP); + + if (hResult == null || szDbError[0]) + { + delete hDP; + LogError("SQL_Callback_SelectUseKey: %s", szDbError); + return; + } + + hDP.Reset(); + + char szKey[KEYS_MAX_LENGTH], szError[PMP]; + hDP.ReadString(SZF(szKey)); + int iClient = CID(hDP.ReadCell()); + ReplySource CmdReplySource = view_as(hDP.ReadCell()); + bool bNotify = view_as(hDP.ReadCell()); + + Handle hPlugin = null; + Function fCallback = INVALID_FUNCTION; + any iData = 0; + if(hDP.ReadCell()) + { + hPlugin = view_as(hDP.ReadCell()); + fCallback = hDP.ReadFunction(); + iData = hDP.ReadCell(); + } + + delete hDP; + + if (iClient) + { + if(hResult.FetchRow()) + { + char szKeyType[KEYS_MAX_LENGTH]; + hResult.FetchString(1, SZF(szKeyType)); + DataPack hDataPack; + if(g_hKeysTrie.GetValue(szKeyType, hDataPack)) + { + int iExpires = hResult.FetchInt(2); + if(iExpires) + { + if(iExpires < GetTime()) + { + Keys_Delete(szKey); + FormatEx(SZF(szError), "%T%T", "ERROR", iClient, "ERROR_KEY_NOT_EXIST", iClient); + if(bNotify) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, szError); + } + if(fCallback) + { + API_Callback(Use, hPlugin, fCallback, iClient, szKey, false, szError, iData); + } + return; + } + } + + int iUses = hResult.FetchInt(3); + if(!iUses) + { + Keys_Delete(szKey); + FormatEx(SZF(szError), "%T%T", "%t%t", "ERROR", iClient, "ERROR_KEY_NOT_EXIST", iClient); + if(bNotify) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, szError); + } + if(fCallback) + { + API_Callback(Use, hPlugin, fCallback, iClient, szKey, false, szError, iData); + } + return; + } + + int iKeyID = hResult.FetchInt(0); + + DataPack hDP2 = new DataPack(); + hDP2.WriteString(szKey); + hDP2.WriteString(szKeyType); + hDP2.WriteCell(iKeyID); + hDP2.WriteCell(iUses); + hDP2.WriteCell(UID(iClient)); + hDP2.WriteCell(CmdReplySource); + hDP2.WriteCell(bNotify); + + if(hPlugin != null && fCallback != INVALID_FUNCTION) + { + hDP2.WriteCell(true); + hDP2.WriteCell(hPlugin); + hDP2.WriteFunction(fCallback); + hDP2.WriteCell(iData); + } + else + { + hDP2.WriteCell(false); + } + char szQuery[PMP], szAuth[32]; + GetClientAuthId(iClient, AuthId_Engine, SZF(szAuth)); + FormatEx(SZF(szQuery), "SELECT `u_auth` FROM `keys_players_used` WHERE `u_kid` = '%d' AND `u_auth` = '%s';", iKeyID, szAuth); + g_hDatabase.Query(SQL_Callback_CheckUseKey, szQuery, hDP2); + + return; + } + + FormatEx(SZF(szError), "%T%T", "ERROR", iClient, "ERROR_INCORRECT_TYPE", iClient); + if(fCallback) + { + API_Callback(Use, hPlugin, fCallback, iClient, szKey, false, szError, iData); + } + return; + } + + FormatEx(SZF(szError), "%T%T", "ERROR", iClient, "ERROR_KEY_NOT_EXIST", iClient); + if(fCallback) + { + API_Callback(Use, hPlugin, fCallback, iClient, szKey, false, szError, iData); + } + } +} + +public void SQL_Callback_CheckUseKey(Database hDB, DBResultSet hResult, const char[] szDbError, any hCbDP) +{ + DataPack hDP = view_as(hCbDP); + + if (hResult == null || szDbError[0]) + { + delete hDP; + LogError("SQL_Callback_CheckUseKey: %s", szDbError); + return; + } + + hDP.Reset(); + + char szKey[KEYS_MAX_LENGTH], szKeyType[KEYS_MAX_LENGTH]; + hDP.ReadString(SZF(szKey)); + hDP.ReadString(SZF(szKeyType)); + int iKeyID = hDP.ReadCell(); + hDP.ReadCell(); + int iClient = CID(hDP.ReadCell()); + hDP.ReadCell(); + hDP.ReadCell(); + + Handle hPlugin = null; + Function fCallback = INVALID_FUNCTION; + any iData = 0; + if(hDP.ReadCell()) + { + hPlugin = view_as(hDP.ReadCell()); + fCallback = hDP.ReadFunction(); + iData = hDP.ReadCell(); + } + + if(hResult.FetchRow()) + { + char szError[PMP]; + FormatEx(SZF(szError), "%T%T", "%t%t", "ERROR", iClient, "ERROR_KEY_ALREADY_USED", iClient); + API_Callback(Use, hPlugin, fCallback, iClient, szKey, false, szError, iData); + delete hDP; + return; + } + + char szQuery[PMP]; + FormatEx(SZF(szQuery), "SELECT `p_num`, `p_value` FROM `keys_params` WHERE `p_kid` = '%d' ORDER BY `p_num`;", iKeyID); + g_hDatabase.Query(SQL_Callback_UseKey, szQuery, hDP); +} + +public void SQL_Callback_UseKey(Database hDB, DBResultSet hResult, const char[] szDbError, any hCbDP) +{ + DataPack hDP = view_as(hCbDP); + + if (hResult == null || szDbError[0]) + { + delete hDP; + LogError("SQL_Callback_SelectUseKey: %s", szDbError); + return; + } + + hDP.Reset(); + + char szKey[KEYS_MAX_LENGTH], szKeyType[KEYS_MAX_LENGTH], szError[PMP]; + hDP.ReadString(SZF(szKey)); + hDP.ReadString(SZF(szKeyType)); + int iKeyID = hDP.ReadCell(); + int iUses = hDP.ReadCell(); + int iClient = CID(hDP.ReadCell()); + ReplySource CmdReplySource = view_as(hDP.ReadCell()); + bool bNotify = view_as(hDP.ReadCell()); + + Handle hPlugin = null; + Function fCallback = INVALID_FUNCTION; + any iData = 0; + if(hDP.ReadCell()) + { + hPlugin = view_as(hDP.ReadCell()); + fCallback = hDP.ReadFunction(); + iData = hDP.ReadCell(); + + if(!hResult.RowCount) + { + API_Callback(Use, hPlugin, fCallback, iClient, szKey, false, "Fail select key params", iData); + delete hDP; + return; + } + } + + if (iClient) + { + if(!hResult.RowCount) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "Fail select key params"); + } + + ArrayList hParamsArr = new ArrayList(ByteCountToCells(KEYS_MAX_LENGTH)); + + char szParam[KEYS_MAX_LENGTH]; + + while(hResult.FetchRow()) + { + hResult.FetchString(1, SZF(szParam)); + hParamsArr.PushString(szParam); + } + + DataPack hDataPack; + g_hKeysTrie.GetValue(szKeyType, hDataPack); + hDataPack.Reset(); + hPlugin = view_as(hDataPack.ReadCell()); + fCallback = hDataPack.ReadFunction(); + + strcopy(SZF(szError), "unknown"); + bool bResult = false; + Call_StartFunction(hPlugin, fCallback); + Call_PushCell(Activation); + Call_PushCell(iClient); + Call_PushString(szKeyType); + Call_PushCell(hParamsArr); + Call_PushStringEx(SZF(szError), SM_PARAM_STRING_UTF8|SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); + Call_PushCell(sizeof(szError)); + Call_Finish(bResult); + + delete hParamsArr; + + if(!bResult && bNotify) + { + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%s", "ERROR", szError); + return; + } + + char szName[MAX_NAME_LENGTH], szAuth[32], szQuery[PMP], szSID[64]; + GetClientName(iClient, SZF(szName)); + GetClientAuthId(iClient, AuthId_Engine, SZF(szAuth)); + + if(!g_CVAR_iServerID) + { + szSID[0] = 0; + } + else + { + FormatEx(SZF(szSID), " AND `k_sid` = %d", g_CVAR_iServerID); + } + if(--iUses) + { + if(!g_CVAR_iServerID) + { + FormatEx(SZF(szQuery), "INSERT INTO `keys_players_used` (`u_auth`, `u_kid`) VALUES ('%s', %d);", szAuth, iKeyID); + } + else + { + FormatEx(SZF(szQuery), "INSERT INTO `keys_players_used` (`u_auth`, `u_kid`, `u_sid`) VALUES ('%s', %d, %d);", szAuth, iKeyID, g_CVAR_iServerID); + } + g_hDatabase.Query(SQL_Callback_ErrorCheck, szQuery); + + FormatEx(SZF(szQuery), "UPDATE `keys_tokens` SET `k_uses` = %d WHERE `u_kid` = %d%s;", iUses, iKeyID, szSID); + g_hDatabase.Query(SQL_Callback_ErrorCheck, szQuery); + } + else + { + Keys_Delete(szKey); + FormatEx(SZF(szQuery), "DELETE FROM `keys_players_used` WHERE `u_kid` = %d%s;", szKey, szSID); + g_hDatabase.Query(SQL_Callback_ErrorCheck, szQuery); + } + + UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", "SUCCESS_USE_KEY", szKey); + LogToFile(g_sLogFile, "%T", "LOG_SUCCESS_USE_KEY", LANG_SERVER, szName, szAuth, szKey); + return; + } +} diff --git a/Core/addons/sourcemod/scripting/keys/STATS.sp b/Core/addons/sourcemod/scripting/keys/STATS.sp new file mode 100644 index 0000000..fd0b993 --- /dev/null +++ b/Core/addons/sourcemod/scripting/keys/STATS.sp @@ -0,0 +1,322 @@ + +#undef REQUIRE_EXTENSIONS +#tryinclude +#tryinclude +#tryinclude +#tryinclude + +#define SOCKET_ON() (GetFeatureStatus(FeatureType_Native, "SocketCreate") == FeatureStatus_Available) +#define CURL_ON() (GetFeatureStatus(FeatureType_Native, "curl_easy_init") == FeatureStatus_Available) +#define STEAMWORKS_ON() (GetFeatureStatus(FeatureType_Native, "SteamWorks_CreateHTTPRequest") == FeatureStatus_Available) +#define RIP_ON() (GetFeatureStatus(FeatureType_Native, "HTTPClient.HTTPClient") == FeatureStatus_Available) + +stock const char API_KEY[] = "35bdcf38c4dabc22028792ebb366b3b8"; +stock const char URL[] = "http://stats.tibari.ru/add_server.php"; +stock const char HOST[] = "http://stats.tibari.ru"; +stock const char SCRIPT[] = "add_server.php"; + +void Stats_Init() +{ +#if defined _socket_included + MarkNativeAsOptional("SocketCreate"); + MarkNativeAsOptional("SocketConnect"); + MarkNativeAsOptional("SocketSend"); +#endif +#if defined _cURL_included + MarkNativeAsOptional("curl_slist"); + MarkNativeAsOptional("curl_slist_append"); + MarkNativeAsOptional("curl_easy_init"); + MarkNativeAsOptional("curl_easy_setopt_string"); + MarkNativeAsOptional("curl_easy_setopt_int"); + MarkNativeAsOptional("curl_easy_setopt_handle"); + MarkNativeAsOptional("curl_easy_setopt_function"); + MarkNativeAsOptional("curl_easy_perform_thread"); + MarkNativeAsOptional("curl_easy_strerror"); +#endif + +#if defined _SteamWorks_Included + MarkNativeAsOptional("SteamWorks_CreateHTTPRequest"); + MarkNativeAsOptional("SteamWorks_SetHTTPRequestRawPostBody"); + MarkNativeAsOptional("SteamWorks_SetHTTPCallbacks"); + MarkNativeAsOptional("SteamWorks_WriteHTTPResponseBodyToFile"); + MarkNativeAsOptional("SteamWorks_SendHTTPRequest"); +#endif +#if defined _ripext_included_ + MarkNativeAsOptional("HTTPClient.HTTPClient"); + MarkNativeAsOptional("HTTPClient.SetHeader"); + MarkNativeAsOptional("HTTPClient.Post"); + MarkNativeAsOptional("HTTPResponse.Data.get"); + MarkNativeAsOptional("HTTPResponse.Status.get"); + MarkNativeAsOptional("JSONObject.JSONObject"); + MarkNativeAsOptional("JSONObject.SetString"); +#endif +} + +static ConVar g_hCvar_GetIPMethod; + +void Stats_OnPluginStart() +{ + g_hCvar_GetIPMethod = CreateConVar("sm_keys_stats_get_ip_method", "0", " IP-\n\ + 0 - hostip\n\ + 1 - status\n\ + 123.123.123.123:12345 - "); +} + +void Stats_OnMapStart() +{ + #if defined _SteamWorks_Included + if (CanTestFeatures() && STEAMWORKS_ON()) + { + SteamWorks_SteamServersConnected(); + return; + } + #endif + + CreateTimer(4.0, Timer_Connect, _, TIMER_FLAG_NO_MAPCHANGE); +} + +public Action Timer_Connect(Handle hTimer, any iData) +{ + #if defined _ripext_included_ + if (CanTestFeatures() && RIP_ON()) + { + RiP_SendKeysInfo(); + return; + } + #endif + + #if defined _ripext_included_ + if (CanTestFeatures() && SOCKET_ON()) + { + Socket_SendKeysInfo(); + return; + } + #endif + + #if defined _ripext_included_ + if (CanTestFeatures() && CURL_ON()) + { + cURL_SendKeysInfo(); + return; + } + #endif + + SetFailState("[VIP STATS] : SteamWorks, Rest in Pawn, Socket, CURL"); +} + +#if defined _socket_included +void Socket_SendKeysInfo() +{ + Handle hSocket = SocketCreate(SOCKET_TCP, OnSocketError); + SocketConnect(hSocket, OnSocketConnected, OnSocketReceive, OnSocketDisconnected, HOST[7], 80); +} + +public int OnSocketConnected(Handle hSocket, any arg) +{ + char szBuffer[512], szBody[PMP], szIP[24]; + + GetServerIP(SZF(szIP)); + + FormatEx(SZF(szBody), "key=%s&ip=%s&version=%s&sm=%s", API_KEY, szIP, PLUGIN_VERSION, SOURCEMOD_VERSION); + FormatEx(SZF(szBuffer), "POST /%s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\nContent-Length: %d\r\nUser-Agent: Valve/Steam HTTP Client 1.0\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n%s\r\n", SCRIPT, HOST[7], strlen(szBody), szBody); + + SocketSend(hSocket, szBuffer); +} + +public int OnSocketReceive(Handle hSocket, const char[] sReceiveData, const int iDataSize, any data) +{ + CloseHandle(hSocket); + + int iStartIndex = FindCharInString(sReceiveData, ' '); + if(iStartIndex != -1) + { + char sBuffer[4]; + strcopy(SZF(sBuffer), sReceiveData[iStartIndex+1]); + sBuffer[3] = 0; + ResultNotify(StringToInt(sBuffer), "Socket"); + } +} + +public int OnSocketDisconnected(Handle hSocket, any data) +{ + CloseHandle(hSocket); +} + +public int OnSocketError(Handle hSocket, const int errorType, const int errorNum, any data) +{ + LogError("OnSocketError:: errorType %d (errorNum %d)", errorType, errorNum); + CloseHandle(hSocket); +} +#endif + +#if defined _cURL_included +void cURL_SendKeysInfo() +{ + char szIP[24], szBody[PMP]; + + GetServerIP(SZF(szIP)); + + FormatEx(SZF(szBody), "key=%s&ip=%s&version=%s&sm=%s", API_KEY, szIP, PLUGIN_VERSION, SOURCEMOD_VERSION); + + Handle hBuffer = curl_slist(); + curl_slist_append(hBuffer, "User-Agent: Valve/Steam HTTP Client 1.0"); + + Handle hCurl = curl_easy_init(); + curl_easy_setopt_string(hCurl, CURLOPT_URL, URL); + curl_easy_setopt_int(hCurl, CURLOPT_HTTPPOST, 1); + curl_easy_setopt_string(hCurl, CURLOPT_POSTFIELDS, szBody); + curl_easy_setopt_handle(hCurl, CURLOPT_HTTPHEADER, hBuffer); + curl_easy_setopt_int(hCurl, CURLOPT_POSTFIELDSIZE, strlen(szBody)); + curl_easy_setopt_function(hCurl, CURLOPT_WRITEFUNCTION, OnCurlWrite); + curl_easy_perform_thread(hCurl, OnComplete, hBuffer); +} + +public int OnCurlWrite(Handle hCurl, const char[] szBuffer, const int bytes, const int nmemb) +{ + if(!strcmp(szBuffer, "Success!")) + { + LogAction(-1, -1, "[KEYS-CORE STATS] [cURL] "); + } + else + { + LogError("[KEYS-CORE STATS] [cURL] / (%s)", szBuffer); + } + + return bytes*nmemb; +} + +public int OnComplete(Handle hCurl, CURLcode code, any hHeader) +{ + CloseHandle(hCurl); + CloseHandle(hHeader); + + if(code != CURLE_OK) + { + char error[PLATFORM_MAX_PATH]; + curl_easy_strerror(code, SZF(error)); + LogError("cURL error: (%i) '%s'", code, error); + } +} +#endif + +#if defined _ripext_included_ +void RiP_SendKeysInfo() +{ + HTTPClient g_hHTTPClient = new HTTPClient(HOST); + + char szUserAgent[64], szIP[24]; +// FormatEx(SZF(szUserAgent), "SourcePawn (VIP Stats v%s)", PLUGIN_VERSION); + FormatEx(SZF(szUserAgent), "Valve/Steam HTTP Client 1.0"); + g_hHTTPClient.SetHeader("User-Agent", szUserAgent); + + GetServerIP(SZF(szIP)); + + JSONObject hRequest = new JSONObject(); + hRequest.SetString("key", API_KEY); + hRequest.SetString("ip", szIP); + hRequest.SetString("version", PLUGIN_VERSION); + hRequest.SetString("sm", SOURCEMOD_VERSION); + + g_hHTTPClient.Post(SCRIPT, hRequest, OnRequestComplete, 0); + delete hRequest; +} + +public void OnRequestComplete(HTTPResponse hResponse, any iData) +{ + ResultNotify(view_as(hResponse.Status), "Rest in Pawn"); +} +#endif + +#if defined _SteamWorks_Included +public void SteamWorks_SteamServersConnected() +{ + int iIp[4]; + if (SteamWorks_GetPublicIP(iIp) && iIp[0] && iIp[1] && iIp[2] && iIp[3]) + { + char szIP[24], szBuffer[PMP]; + FormatEx(SZF(szIP), "%d.%d.%d.%d:%d", iIp[0], iIp[1], iIp[2], iIp[3], FindConVar("hostport").IntValue); + + FormatEx(SZF(szBuffer), "%s/%s", HOST, SCRIPT); + Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodPOST, szBuffer); + FormatEx(SZF(szBuffer), "key=%s&ip=%s&version=%s&sm=%s", API_KEY, szIP, PLUGIN_VERSION, SOURCEMOD_VERSION); + SteamWorks_SetHTTPRequestRawPostBody(hRequest, "application/x-www-form-urlencoded", SZF(szBuffer)); + SteamWorks_SetHTTPCallbacks(hRequest, OnTransferComplete); + SteamWorks_SendHTTPRequest(hRequest); + } +} + +public int OnTransferComplete(Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode) +{ + delete hRequest; + + ResultNotify(view_as(eStatusCode), "SteamWorks"); +} +#endif + +void ResultNotify(int iStatusCode, const char[] szPrefix) +{ + switch(iStatusCode) + { + case 200: LogAction(-1, -1, "[KEYS-CORE STATS] [%s] /", szPrefix); + case 400: LogError("[KEYS-CORE STATS] [%s] ", szPrefix); + case 403: LogError("[KEYS-CORE STATS] [%s] IP:PORT", szPrefix); + case 404: LogError("[KEYS-CORE STATS] [%s] ", szPrefix); + case 406: LogError("[KEYS-CORE STATS] [%s] API KEY", szPrefix); + case 410: LogError("[KEYS-CORE STATS] [%s] KEYS-CORE", szPrefix); + case 413: LogError("[KEYS-CORE STATS] [%s] ", szPrefix); + default: LogError("[KEYS-CORE STATS] [%s] : %d", szPrefix, iStatusCode); + } +} + +#define GetServerIp(%1,%2) GetServerIpFunc(view_as(%1), %1, %2) + +void GetServerIpFunc(int[] array, char[] buffer, int maxlength) +{ + array[0] = FindConVar("hostip").IntValue; + FormatEx(buffer, maxlength, "%d.%d.%d.%d:%d", buffer[3] + 0, buffer[2] + 0, buffer[1] + 0, buffer[0] + 0, FindConVar("hostport").IntValue); +} + +void GetServerIP(char[] szIP, int iMaxLen) +{ + g_hCvar_GetIPMethod.GetString(szIP, iMaxLen); + if(strlen(szIP) > 12) + { + return; + } + + if(StringToInt(szIP) == 1) + { + char szResponse[512]; + ServerCommandEx(SZF(szResponse), "status"); + int index = StrContains(szResponse[50], "udp/ip", true); + if(index != -1) + { + int iIpPos, iPortPos; + index += FindCharInString(szResponse[56+index], ':')+58; + strcopy(szResponse, 64, szResponse[index]); + + iPortPos = FindCharInString(szResponse, ':'); + if(StrContains(szResponse[iPortPos+9], "public", true) != -1) + { + iIpPos = iPortPos+20; + } + else + { + iIpPos = 0; + } + + index = 0; + while((szResponse[iIpPos+index] == '.' || IsCharNumeric(szResponse[iIpPos+index])) && index < iMaxLen) + { + szIP[index] = szResponse[iIpPos+index]; + ++index; + } + + strcopy(szIP[index], 7, szResponse[iPortPos]); + szIP[index+7] = 0; + return; + } + } + + GetServerIp(szIP, iMaxLen); +} \ No newline at end of file diff --git a/Core/addons/sourcemod/scripting/keys/UTIL.sp b/Core/addons/sourcemod/scripting/keys/UTIL.sp new file mode 100644 index 0000000..bab6c2b --- /dev/null +++ b/Core/addons/sourcemod/scripting/keys/UTIL.sp @@ -0,0 +1,70 @@ + +void UTIL_ReplyToCommand(int iClient, ReplySource CmdReplySource, const char[] szFormat, any ...) +{ + char szBuffer[2048]; + SetGlobalTransTarget(iClient); + VFormat(SZF(szBuffer), szFormat, 4); + + if(iClient) + { + switch(CmdReplySource) + { + case SM_REPLY_TO_CONSOLE: PrintToConsole(iClient, "[KEYS] %s", szBuffer); + case SM_REPLY_TO_CHAT: PrintToChat(iClient, GetEngineVersion() == Engine_CSGO ? " \x04[KEYS] \x01%s":"\x04[KEYS] \x01%s", szBuffer); + } + } + else + { + PrintToServer("[KEYS] %s", szBuffer); + } +} + +int UTIL_GetRandomInt(int iMin, int iMax) +{ + int iRandom = GetURandomInt(); + + if (iRandom == 0) + { + ++iRandom; + } + + return RoundToCeil(float(iRandom) / (float(2147483647) / float(iMax - iMin + 1))) + iMin - 1; +} + +/* +A - Буква в любом регистре +B - Цифра 0-9 +X - Цифра 0-9 либо буква в любом регистре +U - число 0-9 либо буква в верхнем регистре +L - число 0-9 либо буква в нижнем регистре +*/ + +int UTIL_GetCharTemplate(char iChar) +{ + + static const int g_iNumbers[] = {0x30, 0x39}; + static const int g_iLettersUpper[] = {0x41, 0x5A}; + static const int g_iLettersLower[] = {0x61, 0x7A}; + switch(iChar) + { + // A - буква в любом регистре + case 0x41: return UTIL_GetRandomInt(1, 20) > 10 ? UTIL_GetRandomInt(g_iLettersUpper[0], g_iLettersUpper[1]):UTIL_GetRandomInt(g_iLettersLower[0], g_iLettersLower[1]); + // B - число 0-9 + case 0x42: return UTIL_GetRandomInt(g_iNumbers[0], g_iNumbers[1]); + // X - число 0-9 либо буква в любом регистре + case 0x58: return UTIL_GetRandomInt(0, 2) == 1 ? UTIL_GetRandomInt(g_iNumbers[0], g_iNumbers[1]):(UTIL_GetRandomInt(1, 20) > 10 ? UTIL_GetRandomInt(g_iLettersUpper[0], g_iLettersUpper[1]):UTIL_GetRandomInt(g_iLettersLower[0], g_iLettersLower[1])); + // U - число 0-9 либо буква в верхнем регистре + case 0x55: return UTIL_GetRandomInt(0, 2) == 1 ? UTIL_GetRandomInt(g_iNumbers[0], g_iNumbers[1]):UTIL_GetRandomInt(g_iLettersUpper[0], g_iLettersUpper[1]); + // L - число 0-9 либо буква в нижнем регистре + case 0x4c: return UTIL_GetRandomInt(0, 2) == 1 ? UTIL_GetRandomInt(g_iNumbers[0], g_iNumbers[1]):UTIL_GetRandomInt(g_iLettersLower[0], g_iLettersLower[1]); + // Символ - + case 0x2D: return iChar; + // Другой символ + default: + { + return UTIL_GetCharTemplate(0x58); + } + } + + return iChar; +} \ No newline at end of file diff --git a/Core/addons/sourcemod/scripting/keys/VARS.sp b/Core/addons/sourcemod/scripting/keys/VARS.sp new file mode 100644 index 0000000..e9f0b85 --- /dev/null +++ b/Core/addons/sourcemod/scripting/keys/VARS.sp @@ -0,0 +1,52 @@ + +#define SZF(%0) %0, sizeof(%0) +#define SZFA(%0,%1) %0[%1], sizeof(%0[]) +#define CID(%0) GetClientOfUserId(%0) +#define UID(%0) GetClientUserId(%0) + +#define I2S(%0,%1) IntToString(%0, SZF(%1)) +#define S2I(%0) StringToInt(%0) + +#define PMP PLATFORM_MAX_PATH +#define MNL MAX_NAME_LENGTH +#define MPL MAXPLAYERS +#define MCL MaxClients + +char g_sLogFile[PMP]; + +bool g_bIsStarted; +Database g_hDatabase; +bool g_bDBMySQL; + +bool g_bIsBlocked[MPL+1]; +int g_iAttempts[MPL+1]; + +StringMap g_hKeysTrie; +ArrayList g_hKeysArray; + +int g_CVAR_iServerID; +int g_CVAR_iKeyLength; +char g_CVAR_sKeyTemplate[KEYS_MAX_LENGTH]; +int g_CVAR_iAttempts; +int g_CVAR_iBlockTime; + +int GET_UID(int iClient) +{ + return iClient == 0 ? 0:UID(iClient); +} + +int GET_CID(int iClient) +{ + if(iClient > 0) + { + iClient = CID(iClient); + if(!iClient) + { + return -1; + } + + return iClient; + } + + return iClient; +} \ No newline at end of file diff --git a/addons/sourcemod/translations/keys_core.phrases.txt b/Core/addons/sourcemod/translations/keys_core.phrases.txt similarity index 100% rename from addons/sourcemod/translations/keys_core.phrases.txt rename to Core/addons/sourcemod/translations/keys_core.phrases.txt diff --git a/Core/keys_core_logo_.png b/Core/keys_core_logo_.png new file mode 100644 index 0000000..31119f9 Binary files /dev/null and b/Core/keys_core_logo_.png differ diff --git a/Modules/addons/sourcemod/plugins/Keys_VIP.smx b/Modules/addons/sourcemod/plugins/Keys_VIP.smx new file mode 100644 index 0000000..5f85170 Binary files /dev/null and b/Modules/addons/sourcemod/plugins/Keys_VIP.smx differ diff --git a/Modules/addons/sourcemod/scripting/Keys_VIP.sp b/Modules/addons/sourcemod/scripting/Keys_VIP.sp new file mode 100644 index 0000000..bbd88a6 --- /dev/null +++ b/Modules/addons/sourcemod/scripting/Keys_VIP.sp @@ -0,0 +1,269 @@ +#pragma newdecls required +#pragma semicolon 1 + +#include +#include + +public Plugin myinfo = { + name = "[Keys] VIP", + author = "R1KO & T1MOX4", + version = "1.4", + url = "hlmod.ru" +}; + +#define EXT_STATUS 1 // Разрешить ли ключам типа vip_add продлевать VIP-статус +#define GC_STATUS 0 // Разрешить ли ключам типа vip_add изменять VIP-группу (работает только если включен EXT_STATUS) +#define CMP_VGRP 1 // Ключ типа vip_add может продлевать VIP-статус только если VIP-группа совпадает (работает только если включен EXT_STATUS) + // Если включено - отключает GC_STATUS + +#if CMP_VGRP == 1 && GC_STATUS == 1 +#undef GC_STATUS +#define GC_STATUS 0 +#endif + +static const char g_sKeyType[][] = {"vip_add", "vip_ext", "vip_gc"}; + +public void OnPluginStart() { + LoadTranslations("keys_core.phrases"); + LoadTranslations("keys_vip_module.phrases"); + + if (Keys_IsCoreStarted()) Keys_OnCoreStarted(); +} + +public void OnPluginEnd() { + for(int i; i < sizeof(g_sKeyType); ++i) { + Keys_UnregKey(g_sKeyType[i]); + } +} + +public void Keys_OnCoreStarted() { + for(int i; i < sizeof(g_sKeyType); ++i) { + Keys_RegKey(g_sKeyType[i], KeyCallback); + } +} + +public bool KeyCallback(KeysAction eKeysAction, int iClient, const char[] szKeyType, ArrayList hParamsArr, char[] szBuffer, int iBuffLen) { + char sGroup[KEYS_MAX_LENGTH]; + switch(eKeysAction) { + case Validation: { + if (!strcmp(szKeyType, g_sKeyType[0])) { + if (hParamsArr.Length != 2) { + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_NUM_ARGS", iClient); + return false; + } + + hParamsArr.GetString(0, sGroup, sizeof(sGroup)); + + if (!VIP_IsValidVIPGroup(sGroup)) { + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_INVALID_GROUP", iClient); + return false; + } + + hParamsArr.GetString(1, sGroup, sizeof(sGroup)); + int iTime = StringToInt(sGroup); + + if (iTime < 0) { + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_INVALID_TIME", iClient); + return false; + } + + IntToString(VIP_TimeToSeconds(iTime), sGroup, sizeof(sGroup)); + hParamsArr.SetString(1, sGroup); + + return true; + } + + if (hParamsArr.Length != 1) { + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_NUM_ARGS", iClient); + return false; + } + + hParamsArr.GetString(0, sGroup, sizeof(sGroup)); + + if (!strcmp(szKeyType, g_sKeyType[1])) { + int iTime = StringToInt(sGroup); + + if (iTime < 0) { + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_INVALID_TIME", iClient); + return false; + } + + IntToString(VIP_TimeToSeconds(iTime), sGroup, sizeof(sGroup)); + hParamsArr.SetString(0, sGroup); + + return true; + } + + if (!VIP_IsValidVIPGroup(sGroup)) { + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_INVALID_GROUP", iClient); + return false; + } + + return true; + } + + case Activation: { + int iClientID = -1; + bool bVip = VIP_IsClientVIP(iClient); + + if (bVip) { + iClientID = VIP_GetClientID(iClient); + } + + if (!strcmp(szKeyType, g_sKeyType[0])) { + hParamsArr.GetString(0, sGroup, sizeof(sGroup)); + + if (!VIP_IsValidVIPGroup(sGroup)) { + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_INVALID_GROUP", iClient); + return false; + } + + if (bVip) { + // && VIP_GetClientAuthType(iClient) < VIP_AuthType:3 + if (iClientID != -1) { + #if EXT_STATUS == 1 + int iClientTime = VIP_GetClientAccessTime(iClient); + if (!iClientTime) { + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_CAN_NOT_USE", iClient); + return false; + } + + #if GC_STATUS == 1 || CMP_VGRP == 1 + if (VIP_IsValidVIPGroup(sGroup)) { + char sClientGroup[64]; + VIP_GetClientVIPGroup(iClient, sClientGroup, sizeof(sClientGroup)); + + if (strcmp(sClientGroup, sGroup)) { + #if CMP_VGRP == 1 + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_CAN_NOT_USE", iClient); + return false; + #elseif GC_STATUS == 1 + VIP_SetClientVIPGroup(iClient, sGroup, true); + PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "USE_KEY_GRP_CNG", sGroup); + #endif + } + } + #endif + + hParamsArr.GetString(1, sGroup, sizeof(sGroup)); + int iTime = StringToInt(sGroup); + + if (iTime) { + Keys_GetTimeFromStamp(sGroup, sizeof(sGroup), iTime, iClient); + iTime += iClientTime; + } else { + FormatEx(sGroup, sizeof(sGroup), "%T", "FOREVER", iClient); + } + + VIP_SetClientAccessTime(iClient, iTime, true); + + PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "USE_KEY_EXT", sGroup); + + return true; + #else + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_VIP_ALREADY", iClient); + return false; + #endif + } + + VIP_RemoveClientVIP2(-1, iClient, false, false); + } + + char sTime[64]; + hParamsArr.GetString(1, sTime, sizeof(sTime)); + int iTime = StringToInt(sTime); + VIP_GiveClientVIP(-1, iClient, iTime, sGroup, true); + + if (iTime) { + Keys_GetTimeFromStamp(sTime, sizeof(sTime), iTime, iClient); + } else { + FormatEx(sTime, sizeof(sTime), "%T", "FOREVER", iClient); + } + + PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "USE_KEY_GOT", sGroup, sTime); + return true; + } + + if (!bVip || (bVip && iClientID == -1)) { + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_CAN_NOT_USE", iClient); + return false; + } + + hParamsArr.GetString(0, sGroup, sizeof(sGroup)); + + if (!strcmp(szKeyType, g_sKeyType[1])) { + int iTime = StringToInt(sGroup); + VIP_SetClientAccessTime(iClient, iTime ? (VIP_GetClientAccessTime(iClient)+iTime):iTime, true); + + if (iTime) { + Keys_GetTimeFromStamp(sGroup, sizeof(sGroup), iTime, iClient); + } else { + FormatEx(sGroup, sizeof(sGroup), "%T", "FOREVER", iClient); + } + + PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "USE_KEY_EXT", sGroup); + + return true; + } + + if (!VIP_IsValidVIPGroup(sGroup)) { + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_INVALID_GROUP", iClient); + return false; + } + + char sClientGroup[64]; + VIP_GetClientVIPGroup(iClient, sClientGroup, sizeof(sClientGroup)); + + if (!strcmp(sClientGroup, sGroup)) { + FormatEx(szBuffer, iBuffLen, "%T", "ERROR_ALREADY_VIP_GROUP", iClient); + return false; + } + + VIP_SetClientVIPGroup(iClient, sGroup, true); + PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "USE_KEY_GRP_CNG", sGroup); + + return true; + } + + case Print: { + hParamsArr.GetString(0, sGroup, sizeof(sGroup)); + + if (!strcmp(szKeyType, g_sKeyType[0])) { + char sTime[64]; + hParamsArr.GetString(1, sTime, sizeof(sTime)); + int iTime = StringToInt(sTime); + + if (iTime) { + Keys_GetTimeFromStamp(sTime, sizeof(sTime), iTime, iClient); + } else { + FormatEx(sTime, sizeof(sTime), "%T", "FOREVER", iClient); + } + + FormatEx(szBuffer, iBuffLen, "%T: %s\t%T: %s", "VIP_GROUP", iClient, sGroup, "TERM", iClient, sTime); + + return true; + } + + if (!strcmp(szKeyType, g_sKeyType[1])) { + char sTime[64]; + int iTime = StringToInt(sGroup); + + if (iTime) { + Keys_GetTimeFromStamp(sTime, sizeof(sTime), iTime, iClient); + } else { + FormatEx(sTime, sizeof(sTime), "%T", "FOREVER", iClient); + } + + FormatEx(szBuffer, iBuffLen, "%T: %s", "TERM", iClient, sTime); + + return true; + } + + FormatEx(szBuffer, iBuffLen, "%T: %s", "VIP_GROUP", iClient, sGroup); + + return true; + } + } + + return false; +} diff --git a/Modules/addons/sourcemod/scripting/include/keys_core.inc b/Modules/addons/sourcemod/scripting/include/keys_core.inc new file mode 100644 index 0000000..7a4ef58 --- /dev/null +++ b/Modules/addons/sourcemod/scripting/include/keys_core.inc @@ -0,0 +1,171 @@ +#if defined _keys_core_included + #endinput +#endif +#define _keys_core_included + +#define KEYS_MAX_LENGTH 64 + +enum KeysAction +{ + Validation = 0, // Валидация параметров ключа + Activation, // Активация ключа + Print // Вывод ключа в консоль/файл +}; + +enum KeysNativeAction +{ + Add = 0, // Добавление/Генерация ключа + Rem, // Удаление ключа + Use // Использование ключа +}; + +// Прототип вызова при валидации параметров/акцивации/выводе параметров ключа +functag public bool:KeyActionCallback(KeysAction:eKeysAction, iClient, const String:szKeyType[], Handle:hParamsArr, String:szBuffer[], iBuffLen); + +funcenum KeyInfoCallback +{ + // Прототип вызова при проверке существования ключа + public(const String:sKey[], bool:bKeyExists, any:iData), + + // Прототип вызова при получении данных ключа + public(const String:sKey[], bool:bKeyExists, const String:sKeyType[], iUses, iExpires, Handle:hParamsArr, any:iData) +}; + +// Прототип вызова при добавлении/удалении/использовании ключа +functag public KeyNativeActionCallback (KeysNativeAction:eKeysAction, iClient, const String:sKey[], bool:bSuccess, const String:sError[], any:iData); + +// Вызывается когда ядро было загружено +forward Keys_OnCoreStarted(); + +// Загружено ли ядро +native bool:Keys_IsCoreStarted(); + +// Получает Handle базы данных +native Handle:Keys_GetCoreDatabase(); + +// Получает тип базы данных (false - SQLite, true - MySQL) +native bool:Keys_GetDatabaseType(); + +// Регистрирует тип ключей +native bool:Keys_RegKey(const String:sKeyType[], KeyActionCallback:fCallback); + +// Разрегистрирует тип ключей +native Keys_UnregKey(const String:sKeyType[]); + +// Проверяет существование типа ключей +native bool:Keys_IsValidKeyType(const String:sKeyType[]); + +// Получает adt_array со всеми типами ключей (нужно закрывать Handle) +native Handle:Keys_FillArrayByKeyTypes(); + +// Проверяет существование ключа +native Keys_IsValidKey(const String:sKey[], KeyInfoCallback:IsValidKeyCallback, any:iData = 0); + +// Получает данные ключа +native Keys_GetKeyData(const String:sKey[], KeyInfoCallback:GetKeyDataCallback, any:iData = 0); + +// Генерирует ключ +native Keys_GenerateKey(String:sBuffer[], iBufLen, const String:sTemplate[] = NULL_STRING); + +// Добавляет ключ +native Keys_AddKey(iClient = 0, const String:sKey[] = NULL_STRING, const String:sKeyType[], iUses, iLifeTime, Handle:hParamsArr, KeyNativeActionCallback:AddKeyCallback, any:iData = 0); + +// Удаляет ключ +native Keys_RemoveKey(iClient = 0, const String:sKey[], KeyNativeActionCallback:RemoveKeyCallback, any:iData = 0); + +// Использует ключ игроком +native Keys_UseKey(iClient, const String:sKey[], bool:bNotify, bool:bIgnoreBlock, KeyNativeActionCallback:UseKeyCallback, any:iData = 0); + +// Для использования не забыть +// LoadTranslations("keys_core.phrases"); +stock Keys_GetTimeFromStamp(String:sBuffer[], iMaxLength, iTimeStamp, iClient = LANG_SERVER) +{ + if (iTimeStamp > 31536000) + { + new iYears = iTimeStamp / 31536000; + new i = iTimeStamp - (iYears*31536000); + if(i > 2592000) + { + FormatEx(sBuffer, iMaxLength, "%d %T %d %T", iYears, "YEARS", iClient, i / 2592000, "MONTHS", iClient); + } + else + { + FormatEx(sBuffer, iMaxLength, "%d %T", iYears, "YEARS", iClient); + } + return; + } + + if (iTimeStamp > 2592000) + { + new iMonths = iTimeStamp / 2592000; + new i = iTimeStamp - (iMonths*2592000); + if (i > 86400) + { + FormatEx(sBuffer, iMaxLength, "%d %T %d %T", iMonths, "MONTHS", iClient, i / 86400, "DAYS", iClient); + } + else + { + FormatEx(sBuffer, iMaxLength, "%d %T", iMonths, "MONTHS", iClient); + } + return; + } + + if (iTimeStamp > 86400) + { + new iDays = iTimeStamp / 86400 % 365; + new iHours = (iTimeStamp / 3600) % 24; + if (iHours > 0) + { + FormatEx(sBuffer, iMaxLength, "%d %T %d %T", iDays, "DAYS", iClient, iHours, "HOURS", iClient); + } + else + { + FormatEx(sBuffer, iMaxLength, "%d %T", iDays, "DAYS", iClient); + } + return; + } + + new iHours = (iTimeStamp / 3600); + new iMins = (iTimeStamp / 60) % 60; + new iSecs = iTimeStamp % 60; + + if (iHours > 0) + { + FormatEx(sBuffer, iMaxLength, "%02d %02d %02d", iHours, iMins, iSecs); + } + else + { + FormatEx(sBuffer, iMaxLength, "%02d %02d", iMins, iSecs); + } +} + +public SharedPlugin:__pl_keys_core= +{ + name = "keys_core", + file = "Keys_Core.smx", +#if defined REQUIRE_PLUGIN + required = 1 +#else + required = 0 +#endif +}; + +#if !defined REQUIRE_PLUGIN + +public __pl_keys_core_SetNTVOptional() +{ + MarkNativeAsOptional("Keys_IsCoreStarted"); + MarkNativeAsOptional("Keys_GetCoreDatabase"); + MarkNativeAsOptional("Keys_GetDatabaseType"); + MarkNativeAsOptional("Keys_RegKey"); + MarkNativeAsOptional("Keys_UnregKey"); + MarkNativeAsOptional("Keys_IsValidKeyType"); + MarkNativeAsOptional("Keys_FillArrayByKeyTypes"); + MarkNativeAsOptional("Keys_IsValidKey"); + MarkNativeAsOptional("Keys_GetKeyData"); + MarkNativeAsOptional("Keys_GenerateKey"); + MarkNativeAsOptional("Keys_AddKey"); + MarkNativeAsOptional("Keys_RemoveKey"); + MarkNativeAsOptional("Keys_UseKey"); +} +#endif diff --git a/addons/sourcemod/translations/keys_vip_module.phrases.txt b/Modules/addons/sourcemod/translations/keys_vip_module.phrases.txt similarity index 100% rename from addons/sourcemod/translations/keys_vip_module.phrases.txt rename to Modules/addons/sourcemod/translations/keys_vip_module.phrases.txt diff --git a/Modules/keys_module_logo.png b/Modules/keys_module_logo.png new file mode 100644 index 0000000..c0646f1 Binary files /dev/null and b/Modules/keys_module_logo.png differ diff --git a/addons/sourcemod/scripting/Keys_Core.sp b/addons/sourcemod/scripting/Keys_Core.sp deleted file mode 100644 index 16c9696..0000000 --- a/addons/sourcemod/scripting/Keys_Core.sp +++ /dev/null @@ -1,440 +0,0 @@ -#pragma semicolon 1 - -#include -#include - -public Plugin:myinfo = -{ - name = "[Keys] Core", - author = "R1KO", - version = "1.4", - url = "hlmod.ru" -}; - -#include "keys/vars.sp" -#include "keys/utils.sp" -#include "keys/api.sp" -#include "keys/cmds.sp" - -public OnPluginStart() -{ - LoadTranslations("keys_core.phrases"); - - g_bIsStarted = false; - g_iServerID = 0; - - BuildPath(Path_SM, SZF(g_sLogFile), "logs/Keys.log"); - - g_hKeysTrie = CreateTrie(); - g_hKeysArray = CreateArray(ByteCountToCells(KEYS_MAX_LENGTH)); - - new Handle:hCvar = CreateConVar("key_length", "32", "Длина генерируемого ключа (8-64)", _, true, 8.0, true, 64.0); - HookConVarChange(hCvar, OnKeyLengthChange); - g_CVAR_iKeyLength = GetConVarInt(hCvar); - - hCvar = CreateConVar("key_template", "", "Шаблон для генерируемого пароля:\n\ - A - Буква в любом регистре\n\ - B - Цифра 0-9\n\ - X - Цифра 0-9 либо буква в любом регистре\n\ - Пример: XXXX-XXXX-XXXX-XXXX", _, false, 0.0, true, 64.0); - - HookConVarChange(hCvar, OnKeyTemplateChange); - GetConVarString(hCvar, SZF(g_CVAR_sKeyTemplate)); - - hCvar = CreateConVar("key_server_id", "0", "ID сервера", _, true, -1.0); - HookConVarChange(hCvar, OnServerIDChange); - g_CVAR_iServerID = GetConVarInt(hCvar); - - hCvar = CreateConVar("key_attempts", "3", "Количество попыток ввода ключа до получения блокировки (0 - Отключено)", _, true, 0.0); - HookConVarChange(hCvar, OnAttemptsChange); - g_CVAR_iAttempts = GetConVarInt(hCvar); - - hCvar = CreateConVar("key_block_time", "60", "На сколько минут будет заблокирован игрок при вводе неверных ключей", _, true, 1.0); - HookConVarChange(hCvar, OnBlockTimeChange); - g_CVAR_iBlockTime = GetConVarInt(hCvar); - - AutoExecConfig(true, "Keys_Core"); - - RegAdminCmds(); - - Connect_DB(); -} - -public OnKeyLengthChange(Handle:hCvar, const String:oldValue[], const String:newValue[]) g_CVAR_iKeyLength = GetConVarInt(hCvar); -public OnKeyTemplateChange(Handle:hCvar, const String:oldValue[], const String:newValue[]) GetConVarString(hCvar, SZF(g_CVAR_sKeyTemplate)); -public OnServerIDChange(Handle:hCvar, const String:oldValue[], const String:newValue[]) -{ - g_CVAR_iServerID = GetConVarInt(hCvar); - if(g_bDBMySQL && g_bIsStarted) - { - GetServerID(false); - } -} -public OnAttemptsChange(Handle:hCvar, const String:oldValue[], const String:newValue[]) g_CVAR_iAttempts = GetConVarInt(hCvar); -public OnBlockTimeChange(Handle:hCvar, const String:oldValue[], const String:newValue[]) g_CVAR_iBlockTime = GetConVarInt(hCvar); - -Connect_DB() -{ - if (SQL_CheckConfig("keys_core")) - { - SQL_TConnect(DB_OnConnect, "keys_core", 1); - } - else - { - decl String:sError[256]; - sError[0] = '\0'; - g_hDatabase = SQLite_UseDatabase("keys_core", SZF(sError)); - DB_OnConnect(g_hDatabase, g_hDatabase, sError, 0); - } -} - -public DB_OnConnect(Handle:owner, Handle:hndl, const String:sError[], any:data) -{ - g_hDatabase = hndl; - - if (g_hDatabase == INVALID_HANDLE || sError[0]) - { - SetFailState("Failed DB Connect %s", sError); - return; - } - - decl String:sDriver[16]; - if(data) - { - SQL_GetDriverIdent(owner, SZF(sDriver)); - } - else - { - SQL_ReadDriver(owner, SZF(sDriver)); - } - - g_bDBMySQL = (strcmp(sDriver, "mysql", false) == 0); - - if (g_bDBMySQL) - { - SQL_TQuery(g_hDatabase, SQL_Callback_ErrorCheck, "SET NAMES 'utf8'"); - SQL_TQuery(g_hDatabase, SQL_Callback_ErrorCheck, "SET CHARSET 'utf8'"); - } - - CreateTables(); -} - -CreateTables() -{ - new Handle:hTxn = SQL_CreateTransaction(); - - if (g_bDBMySQL) - { - SQL_AddQuery(hTxn, "CREATE TABLE IF NOT EXISTS `table_keys` (\ - `key_name` VARCHAR(64) NOT NULL, \ - `type` VARCHAR(64) NOT NULL, \ - `expires` INTEGER UNSIGNED NOT NULL default 0, \ - `uses` INTEGER UNSIGNED NOT NULL default 1, \ - `sid` INTEGER NOT NULL, \ - `param1` VARCHAR(64) NULL default NULL, \ - `param2` VARCHAR(64) NULL default NULL, \ - `param3` VARCHAR(64) NULL default NULL, \ - `param4` VARCHAR(64) NULL default NULL, \ - `param5` VARCHAR(64) NULL default NULL, \ - PRIMARY KEY(`key_name`)) DEFAULT CHARSET=utf8;"); - - SQL_AddQuery(hTxn, "CREATE TABLE IF NOT EXISTS `keys_blocked_players` (\ - `auth` VARCHAR(24) NOT NULL, \ - `block_end` INTEGER UNSIGNED NOT NULL, \ - `sid` INTEGER NOT NULL, \ - PRIMARY KEY(`auth`)) DEFAULT CHARSET=utf8;"); - - SQL_AddQuery(hTxn, "CREATE TABLE IF NOT EXISTS `keys_players_used` (\ - `auth` VARCHAR(24) NOT NULL, \ - `key_name` VARCHAR(64) NOT NULL, \ - `sid` INTEGER NOT NULL) DEFAULT CHARSET=utf8;"); - - SQL_AddQuery(hTxn, "CREATE TABLE IF NOT EXISTS `keys_servers` (\ - `sid` INTEGER NOT NULL AUTO_INCREMENT,\ - `address` VARCHAR(24) NOT NULL, \ - PRIMARY KEY(`sid`), \ - UNIQUE KEY `address` (`address`)) DEFAULT CHARSET=utf8;"); - g_iServerID = -1; - } - else - { - SQL_AddQuery(hTxn, "CREATE TABLE IF NOT EXISTS `table_keys` (\ - `key_name` VARCHAR(64) NOT NULL PRIMARY KEY, \ - `type` VARCHAR(64) NOT NULL, \ - `expires` INTEGER UNSIGNED NOT NULL default 0, \ - `uses` INTEGER UNSIGNED NOT NULL default 1, \ - `param1` VARCHAR(64) NULL default NULL, \ - `param2` VARCHAR(64) NULL default NULL, \ - `param3` VARCHAR(64) NULL default NULL, \ - `param4` VARCHAR(64) NULL default NULL, \ - `param5` VARCHAR(64) NULL default NULL);"); - - SQL_AddQuery(hTxn, "CREATE TABLE IF NOT EXISTS `keys_blocked_players` (\ - `auth` VARCHAR(24) NOT NULL PRIMARY KEY, \ - `block_end` INTEGER UNSIGNED NOT NULL);"); - - SQL_AddQuery(hTxn, "CREATE TABLE IF NOT EXISTS `keys_players_used` (\ - `auth` VARCHAR(24) NOT NULL, \ - `key_name` VARCHAR(64) NOT NULL);"); - g_iServerID = 0; - } - - SQL_ExecuteTransaction(g_hDatabase, hTxn, SQL_Callback_TxnSuccess, SQL_Callback_TxnFailure, 0, DBPrio_High); -} - -public SQL_Callback_TxnFailure(Handle:hDB, any:data, iNumQueries, const String:sError[], iFailIndex, any:queryData[]) -{ - SetFailState("Не удалось создать таблицу (%i): %s", iFailIndex, sError); -} - -public SQL_Callback_TxnSuccess(Handle:hDB, any:data, iNumQueries, Handle:hResults[], any:queryData[]) -{ - if(g_bDBMySQL) - { - SQL_SetCharset(g_hDatabase, "utf8"); - - if(g_iServerID == -1) - { - GetServerID(true); - return; - } - } - - Notify_Started(); -} - -Notify_Started() -{ - g_bIsStarted = true; - - CreateForward_OnCoreStarted(); - - DeleteExpiredKeys(); -} - -public OnConfigsExecuted() -{ - if(g_bIsStarted) - { - DeleteExpiredKeys(); - } -} - -DeleteExpiredKeys() -{ - decl String:sQuery[256]; - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "DELETE FROM `table_keys` WHERE `expires` > 0 AND `expires` < %d;", GetTime()); - } - else - { - FormatEx(SZF(sQuery), "DELETE FROM `table_keys` WHERE `expires` > 0 AND `expires` < %d AND `sid` = %d;", GetTime(), g_iServerID); - } - SQL_TQuery(g_hDatabase, SQL_Callback_ErrorCheck, sQuery); -} - -public SQL_Callback_ErrorCheck(Handle:hOwner, Handle:hResult, const String:sError[], any:data) -{ - if (sError[0]) - { - LogError("SQL_Callback_ErrorCheck: %s", sError); - } -} - -#define GetServerIp(%1,%2) GetServerIpFunc(_:(%1), %1, %2) - -GetServerIpFunc(array[], String:sBuffer[], iMaxLength) -{ - array[0] = GetConVarInt(FindConVar("hostip")); - FormatEx(sBuffer, iMaxLength, "%d.%d.%d.%d:%d", sBuffer[3] + 0, sBuffer[2] + 0, sBuffer[1] + 0, sBuffer[0] + 0, GetConVarInt(FindConVar("hostport"))); -} - -GetServerID(bool:bNotifyStarted) -{ - if(g_CVAR_iServerID == -1) - { - decl String:sAddress[24], String:sQuery[256]; - GetServerIp(sAddress, sizeof(sAddress)); - FormatEx(SZF(sQuery), "SELECT `sid` FROM `keys_servers` WHERE `address` = '%s';", sAddress); - SQL_TQuery(g_hDatabase, SQL_Callback_SelectServerID, sQuery, bNotifyStarted); - return; - } - - g_iServerID = g_CVAR_iServerID; - - if(bNotifyStarted) - { - Notify_Started(); - } -} - -public SQL_Callback_SelectServerID(Handle:hOwner, Handle:hResult, const String:sError[], any:bNotifyStarted) -{ - if (hResult == INVALID_HANDLE || sError[0]) - { - LogError("SQL_Callback_SelectServerID: %s", sError); - return; - } - - if(SQL_FetchRow(hResult)) - { - g_iServerID = SQL_FetchInt(hResult, 0); - - if(bNotifyStarted) - { - Notify_Started(); - } - return; - } - - decl String:sAddress[24], String:sQuery[256]; - GetServerIp(sAddress, sizeof(sAddress)); - FormatEx(SZF(sQuery), "INSERT INTO `keys_servers` (`address`) VALUES ('%s');", sAddress); - SQL_TQuery(g_hDatabase, SQL_Callback_CreateServerID, sQuery, bNotifyStarted); -} - -public SQL_Callback_CreateServerID(Handle:hOwner, Handle:hResult, const String:sError[], any:bNotifyStarted) -{ - if (hResult == INVALID_HANDLE || sError[0]) - { - LogError("SQL_Callback_CreateServerID: %s", sError); - return; - } - - if(SQL_GetAffectedRows(hResult)) - { - g_iServerID = SQL_GetInsertId(g_hDatabase); - - if(bNotifyStarted) - { - Notify_Started(); - } - } -} - -public Action:OnClientSayCommand(iClient, const String:sCommand[], const String:sArgs[]) -{ - if(StrContains(sArgs, "key") != -1) - { - return Plugin_Handled; - } - - return Plugin_Continue; -} - -public OnClientDisconnect(iClient) -{ - g_iAttempts[iClient] = 0; - g_bIsBlocked[iClient] = false; -} - -public OnClientPostAdminCheck(iClient) -{ - if(!IsFakeClient(iClient)) - { - decl String:sQuery[256], String:sAuth[32]; - GetClientAuthId(iClient, AuthId_Engine, SZF(sAuth)); - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "SELECT `block_end` FROM `keys_blocked_players` WHERE `auth` = '%s';", sAuth); - } - else - { - FormatEx(SZF(sQuery), "SELECT `block_end` FROM `keys_blocked_players` WHERE `auth` = '%s' AND `sid` = %d;", sAuth, g_iServerID); - } - SQL_TQuery(g_hDatabase, SQL_Callback_SearchPlayer, sQuery, UID(iClient)); - } -} - -public SQL_Callback_SearchPlayer(Handle:hOwner, Handle:hResult, const String:sError[], any:UserID) -{ - if (hResult == INVALID_HANDLE || sError[0]) - { - LogError("SQL_Callback_SearchPlayer: %s", sError); - return; - } - - new iClient = CID(UserID); - if (iClient) - { - if(SQL_FetchRow(hResult)) - { - g_iAttempts[iClient] = SQL_FetchInt(hResult, 0); - if(g_iAttempts[iClient] < GetTime()) - { - UnBlockClient(iClient); - return; - } - - g_bIsBlocked[iClient] = true; - } - } -} - -BlockClient(iClient) -{ - g_bIsBlocked[iClient] = true; - g_iAttempts[iClient] = GetTime()+(g_CVAR_iBlockTime*60); - decl String:sQuery[256], String:sName[MAX_NAME_LENGTH], String:sAuth[32]; - GetClientName(iClient, SZF(sName)); - GetClientAuthId(iClient, AuthId_Engine, SZF(sAuth)); - - LogToFile(g_sLogFile, "%T", "LOG_BLOCKED", LANG_SERVER, sName, sAuth); - - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "INSERT INTO `keys_blocked_players` (`auth`, `block_end`) VALUES ('%s', %d);", sAuth, g_iAttempts[iClient]); - } - else - { - FormatEx(SZF(sQuery), "INSERT INTO `keys_blocked_players` (`auth`, `block_end`, `sid`) VALUES ('%s', %d, %d);", sAuth, g_iAttempts[iClient], g_iServerID); - } - - SQL_TQuery(g_hDatabase, SQL_Callback_ErrorCheck, sQuery); -} - -UnBlockClient(iClient) -{ - g_bIsBlocked[iClient] = false; - g_iAttempts[iClient] = 0; - decl String:sQuery[256], String:sAuth[32]; - GetClientAuthId(iClient, AuthId_Engine, SZF(sAuth)); - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "DELETE FROM `keys_blocked_players` WHERE `auth` = '%s';", sAuth); - } - else - { - FormatEx(SZF(sQuery), "DELETE FROM `keys_blocked_players` WHERE `auth` = '%s' AND `sid` = %d;", sAuth, g_iServerID); - } - SQL_TQuery(g_hDatabase, SQL_Callback_ErrorCheck, sQuery); -} - -DeleteKey(const String:sKey[], iClient = -1, ReplySource:CmdReplySource = SM_REPLY_TO_CONSOLE) -{ - decl String:sQuery[256], Handle:hDP; - - hDP = CreateDataPack(); - WritePackString(hDP, sKey); - if(iClient == -1) - { - WritePackCell(hDP, false); - } - else - { - WritePackCell(hDP, true); - WritePackCell(hDP, GET_UID(iClient)); - WritePackCell(hDP, CmdReplySource); - } - - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "DELETE FROM `table_keys` WHERE `key_name` = '%s';", sKey); - } - else - { - FormatEx(SZF(sQuery), "DELETE FROM `table_keys` WHERE `key_name` = '%s' AND `sid` = %d;", sKey, g_iServerID); - } - SQL_TQuery(g_hDatabase, SQL_Callback_RemoveKey, sQuery, hDP); -} \ No newline at end of file diff --git a/addons/sourcemod/scripting/Keys_Shop.sp b/addons/sourcemod/scripting/Keys_Shop.sp deleted file mode 100644 index 3320986..0000000 --- a/addons/sourcemod/scripting/Keys_Shop.sp +++ /dev/null @@ -1,218 +0,0 @@ -#pragma semicolon 1 - -#include -#include -#include - -public Plugin:myinfo = -{ - name = "[Keys] Shop", - author = "R1KO", - version = "1.1", - url = "hlmod.ru" -}; - -public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) -{ - MarkNativeAsOptional("Shop_GiveClientItem"); - - return APLRes_Success; -} - -new const String:g_sKeyType[][] = {"shop_credits", "shop_item"}; - -public OnPluginStart() -{ - LoadTranslations("keys_core.phrases"); - LoadTranslations("keys_shop_module.phrases"); - - if (Keys_IsCoreStarted()) Keys_OnCoreStarted(); -} - -public OnPluginEnd() -{ - Keys_UnregKey(g_sKeyType[0]); - Keys_UnregKey(g_sKeyType[1]); -} - -public Keys_OnCoreStarted() -{ - Keys_RegKey(g_sKeyType[0], OnKeyParamsValidate, OnKeyUse, OnKeyPrint); - Keys_RegKey(g_sKeyType[1], OnKeyParamsValidate, OnKeyUse, OnKeyPrint); -} - -public bool:OnKeyParamsValidate(iClient, const String:sKeyType[], Handle:hParamsArr, String:sError[], iErrLen) -{ - decl String:sParam[KEYS_MAX_LENGTH]; - if(!strcmp(sKeyType, g_sKeyType[0])) - { - if(GetArraySize(hParamsArr) != 1) - { - FormatEx(sError, iErrLen, "%T", "ERROR_NUM_ARGS", iClient); - return false; - } - - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - if(StringToInt(sParam) < 1) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_CREDITS", iClient); - return false; - } - - return true; - } - - new iSize = GetArraySize(hParamsArr); - if(!iSize) - { - FormatEx(sError, iErrLen, "%T", "ERROR_NUM_ARGS", iClient); - return false; - } - - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - - new CategoryId:iCatID = Shop_GetCategoryId(sParam); - if(iCatID == INVALID_CATEGORY) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_CATEGORY", iClient); - return false; - } - - if(iSize > 1) - { - GetArrayString(hParamsArr, 1, sParam, sizeof(sParam)); - new ItemId:iItemID = Shop_GetItemId(iCatID, sParam); - if(iItemID == INVALID_ITEM) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_ITEM", iClient); - return false; - } - } - - return true; -} - -GiveClientItem(iClient, ItemId:iItemID) -{ - if(CanTestFeatures() && GetFeatureStatus(FeatureType_Native, "Shop_GiveClientItem") == FeatureStatus_Available) - { - Shop_GiveClientItem(iClient, iItemID); - if(strcmp(SHOP_VERSION, "2.0.24") != 0) - { - Shop_SetClientItemTimeleft(iClient, iItemID, Shop_GetItemValue(iItemID)); - } - } - else - { - new iPrice = Shop_GetItemPrice(iItemID); - Shop_GiveClientCredits(iClient, iPrice, IGNORE_FORWARD_HOOK); - Shop_BuyClientItem(iClient, iItemID); - } -} - -public bool:OnKeyUse(iClient, const String:sKeyType[], Handle:hParamsArr, String:sError[], iErrLen) -{ - decl String:sParam[KEYS_MAX_LENGTH]; - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - if(!strcmp(sKeyType, g_sKeyType[0])) - { - Shop_GiveClientCredits(iClient, StringToInt(sParam), IGNORE_FORWARD_HOOK); - PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "YOU_RECEIVED_CREDITS", StringToInt(sParam)); - return true; - } - - new CategoryId:iCatID = Shop_GetCategoryId(sParam); - if(iCatID == INVALID_CATEGORY) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_CATEGORY", iClient); - return false; - } - - if(GetArraySize(hParamsArr) > 1) - { - decl String:sItem[SHOP_MAX_STRING_LENGTH]; - GetArrayString(hParamsArr, 1, sItem, sizeof(sItem)); - new ItemId:iItemID = Shop_GetItemId(iCatID, sItem); - if(iItemID < ItemId:1) // if(iItemID == INVALID_ITEM) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_ITEM", iClient); - return false; - } - - switch(Shop_GetItemType(iItemID)) - { - case Item_Finite, Item_BuyOnly: - { - GiveClientItem(iClient, iItemID); - } - case Item_Togglable: - { - if(Shop_IsClientHasItem(iClient, iItemID)) - { - Shop_SetClientItemTimeleft(iClient, iItemID, Shop_GetClientItemTimeleft(iClient, iItemID)+Shop_GetItemValue(iItemID)); - } - else - { - GiveClientItem(iClient, iItemID); - } - } - } - PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "YOU_RECEIVED_ITEM_FROM_CATEGORY", sItem, sParam); - - return true; - } - - decl ItemId:iItemID, i, iSize, Handle:hArray; - hArray = Shop_CreateArrayOfItems(iSize); - for (i = 0; i < iSize; ++i) - { - iItemID = Shop_GetArrayItem(hArray, i); - if(Shop_GetItemCategoryId(iItemID) == iCatID) - { - switch(Shop_GetItemType(iItemID)) - { - case Item_Finite, Item_BuyOnly: - { - GiveClientItem(iClient, iItemID); - } - case Item_Togglable: - { - if(Shop_IsClientHasItem(iClient, iItemID)) - { - Shop_SetClientItemTimeleft(iClient, iItemID, Shop_GetClientItemTimeleft(iClient, iItemID)+Shop_GetItemValue(iItemID)); - } - else - { - GiveClientItem(iClient, iItemID); - } - } - } - } - } - PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "YOU_RECEIVED_ALL_ITEMS_FROM_CATEGORY", sParam); - - return true; -} - -public OnKeyPrint(iClient, const String:sKeyType[], Handle:hParamsArr, String:sBuffer[], iBufLen) -{ - decl String:sParam[KEYS_MAX_LENGTH]; - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - if(!strcmp(sKeyType, g_sKeyType[0])) - { - FormatEx(sBuffer, iBufLen, "%T: %s", "CREDITS", iClient, sParam); - return; - } - - FormatEx(sBuffer, iBufLen, "%T: %s", "CATEGORY", iClient, sParam); - - if(GetArraySize(hParamsArr) > 1) - { - GetArrayString(hParamsArr, 1, sParam, sizeof(sParam)); - Format(sBuffer, iBufLen, "%s, %T: %s", sBuffer, "ITEM", iClient, sParam); - } - else - { - Format(sBuffer, iBufLen, "%s, %T: %T", sBuffer, "ITEM", iClient, "ALL", iClient); - } -} diff --git a/addons/sourcemod/scripting/Keys_Store.sp b/addons/sourcemod/scripting/Keys_Store.sp deleted file mode 100644 index d74b050..0000000 --- a/addons/sourcemod/scripting/Keys_Store.sp +++ /dev/null @@ -1,68 +0,0 @@ -#pragma semicolon 1 - -#include -#include -#include - -public Plugin:myinfo = -{ - name = "[Keys] Store (Zephyrus)", - author = "R1KO", - version = "1.0", - url = "hlmod.ru" -}; - -new const String:g_sKeyType[] = "store_credits"; - -public OnPluginStart() -{ - LoadTranslations("keys_core.phrases"); - LoadTranslations("keys_store_module.phrases"); - - if (Keys_IsCoreStarted()) Keys_OnCoreStarted(); -} - -public OnPluginEnd() -{ - Keys_UnregKey(g_sKeyType); -} - -public Keys_OnCoreStarted() -{ - Keys_RegKey(g_sKeyType, OnKeyParamsValidate, OnKeyUse, OnKeyPrint); -} - -public bool:OnKeyParamsValidate(iClient, const String:sKeyType[], Handle:hParamsArr, String:sError[], iErrLen) -{ - decl String:sParam[KEYS_MAX_LENGTH]; - if(GetArraySize(hParamsArr) != 1) - { - FormatEx(sError, iErrLen, "%T", "ERROR_NUM_ARGS", iClient); - return false; - } - - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - if(StringToInt(sParam) < 1) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_CREDITS", iClient); - return false; - } - - return true; -} - -public bool:OnKeyUse(iClient, const String:sKeyType[], Handle:hParamsArr, String:sError[], iErrLen) -{ - decl String:sParam[KEYS_MAX_LENGTH]; - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - Store_SetClientCredits(iClient, Store_GetClientCredits(iClient)+StringToInt(sParam)); - PrintToChat(iClient, "%t", "YOU_RECEIVED_CREDITS", StringToInt(sParam)); - return true; -} - -public OnKeyPrint(iClient, const String:sKeyType[], Handle:hParamsArr, String:sBuffer[], iBufLen) -{ - decl String:sParam[KEYS_MAX_LENGTH]; - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - FormatEx(sBuffer, iBufLen, "%T: %s", "CREDITS", iClient, sParam); -} diff --git a/addons/sourcemod/scripting/Keys_VIP.sp b/addons/sourcemod/scripting/Keys_VIP.sp deleted file mode 100644 index 5af9077..0000000 --- a/addons/sourcemod/scripting/Keys_VIP.sp +++ /dev/null @@ -1,332 +0,0 @@ -#pragma semicolon 1 - -#include -#include -#include - -public Plugin:myinfo = -{ - name = "[Keys] VIP", - author = "R1KO", - version = "1.2", - url = "hlmod.ru" -}; - -#define EXT_STATUS 1 // Разрешить ли ключам типа vip_add продлевать VIP-статус -#define GC_STATUS 0 // Разрешить ли ключам типа vip_add изменять VIP-группу (работает только если включен EXT_STATUS) -#define CMP_VGRP 1 // Ключ типа vip_add может продлевать VIP-статус только если VIP-группа совпадает (работает только если включен EXT_STATUS) - // Если включено - отключает GC_STATUS - -#define USE_VIP_V3 1 // Для компиляции под ядро 3.0 - -new const String:g_sKeyType[][] = {"vip_add", "vip_ext", "vip_gc"}; - -public OnPluginStart() -{ - LoadTranslations("keys_core.phrases"); - LoadTranslations("keys_vip_module.phrases"); - - if (Keys_IsCoreStarted()) Keys_OnCoreStarted(); -} - -public OnPluginEnd() -{ - for(new i = 0; i < sizeof(g_sKeyType); ++i) - { - Keys_UnregKey(g_sKeyType[i]); - } -} - -public Keys_OnCoreStarted() -{ - for(new i = 0; i < sizeof(g_sKeyType); ++i) - { - Keys_RegKey(g_sKeyType[i], OnKeyParamsValidate, OnKeyUse, OnKeyPrint); - } -} - -public bool:OnKeyParamsValidate(iClient, const String:sKeyType[], Handle:hParamsArr, String:sError[], iErrLen) -{ - decl String:sParam[KEYS_MAX_LENGTH]; - if(!strcmp(sKeyType, g_sKeyType[0])) - { - if(GetArraySize(hParamsArr) != 2) - { - FormatEx(sError, iErrLen, "%T", "ERROR_NUM_ARGS", iClient); - return false; - } - - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - if(!VIP_IsValidVIPGroup(sParam)) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_GROUP", iClient); - return false; - } - - GetArrayString(hParamsArr, 1, sParam, sizeof(sParam)); - new iTime = StringToInt(sParam); - if(iTime < 0) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_TIME", iClient); - return false; - } - - IntToString(VIP_TimeToSeconds(iTime), sParam, sizeof(sParam)); - SetArrayString(hParamsArr, 1, sParam); - - return true; - } - - if(GetArraySize(hParamsArr) != 1) - { - FormatEx(sError, iErrLen, "%T", "ERROR_NUM_ARGS", iClient); - return false; - } - - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - - if(!strcmp(sKeyType, g_sKeyType[1])) - { - new iTime = StringToInt(sParam); - if(iTime < 0) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_TIME", iClient); - return false; - } - - IntToString(VIP_TimeToSeconds(iTime), sParam, sizeof(sParam)); - SetArrayString(hParamsArr, 0, sParam); - - return true; - } - - if(!VIP_IsValidVIPGroup(sParam)) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_GROUP", iClient); - return false; - } - - return true; -} - -#if CMP_VGRP == 1 && GC_STATUS == 1 -#undef GC_STATUS -#define GC_STATUS 0 -#endif - -#if USE_VIP_V3 == 0 -public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) -{ - MarkNativeAsOptional("VIP_GetClientID"); - - return APLRes_Success; -} -#endif - -public bool:OnKeyUse(iClient, const String:sKeyType[], Handle:hParamsArr, String:sError[], iErrLen) -{ - decl String:sParam[KEYS_MAX_LENGTH]; - new iClientID = -1; - new bool:bVip = VIP_IsClientVIP(iClient); - if(bVip) - { - #if USE_VIP_V3 == 1 - iClientID = VIP_GetClientID(iClient); - #else - if(CanTestFeatures() && GetFeatureStatus(FeatureType_Native, "VIP_GetClientID") == FeatureStatus_Available) - { - iClientID = VIP_GetClientID(iClient); - } - else - { - GetTrieValue(VIP_GetVIPClientTrie(iClient), "ClientID", iClientID); - } - #endif - } - - if(!strcmp(sKeyType, g_sKeyType[0])) - { - if(bVip) - { - // && VIP_GetClientAuthType(iClient) < VIP_AuthType:3 - if(iClientID != -1) - { - #if EXT_STATUS == 1 - new iClientTime = VIP_GetClientAccessTime(iClient); - if(!iClientTime) - { - FormatEx(sError, iErrLen, "%T", "ERROR_CAN_NOT_USE", iClient); - return false; - } - - #if GC_STATUS == 1 || CMP_VGRP == 1 - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - if(VIP_IsValidVIPGroup(sParam)) - { - decl String:sClientGroup[64]; - VIP_GetClientVIPGroup(iClient, sClientGroup, sizeof(sClientGroup)); - if(strcmp(sClientGroup, sParam) != 0) - { - #if CMP_VGRP == 1 - FormatEx(sError, iErrLen, "%T", "ERROR_CAN_NOT_USE", iClient); - return false; - #else - VIP_SetClientVIPGroup(iClient, sParam, true); - PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "USE_KEY_GRP_CNG", sParam); - #endif - } - #if CMP_VGRP == 1 - VIP_SetClientVIPGroup(iClient, sParam, true); - PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "USE_KEY_GRP_CNG", sParam); - #endif - } - #endif - - GetArrayString(hParamsArr, 1, sParam, sizeof(sParam)); - new iTime = StringToInt(sParam); - if(iTime) - { - Keys_GetTimeFromStamp(sParam, sizeof(sParam), iTime, iClient); - iTime += iClientTime; - } - else - { - FormatEx(sParam, sizeof(sParam), "%T", "FOREVER", iClient); - } - - VIP_SetClientAccessTime(iClient, iTime, true); - - PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "USE_KEY_EXT", sParam); - - return true; - #else - FormatEx(sError, iErrLen, "%T", "ERROR_VIP_ALREADY", iClient); - return false; - #endif - } - } - - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - if(!VIP_IsValidVIPGroup(sParam)) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_GROUP", iClient); - return false; - } - - if(iClientID == -1) - { - VIP_RemoveClientVIP(iClient, false, false); - } - - decl String:sTime[64], iTime; - GetArrayString(hParamsArr, 1, sTime, sizeof(sTime)); - iTime = StringToInt(sTime); - #if USE_VIP_V3 == 1 - VIP_SetClientVIP(0, iClient, iTime, sParam, true); - #else - VIP_SetClientVIP(iClient, iTime, AUTH_STEAM, sParam, true); - #endif - - if(iTime) - { - Keys_GetTimeFromStamp(sTime, sizeof(sTime), iTime, iClient); - } - else - { - FormatEx(sTime, sizeof(sTime), "%T", "FOREVER", iClient); - } - - PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "USE_KEY_GOT", sParam, sTime); - return true; - } - - if(!bVip || (bVip && iClientID == -1)) - { - FormatEx(sError, iErrLen, "%T", "ERROR_CAN_NOT_USE", iClient); - return false; - } - - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - - if(!strcmp(sKeyType, g_sKeyType[1])) - { - new iTime = StringToInt(sParam); - VIP_SetClientAccessTime(iClient, iTime ? (VIP_GetClientAccessTime(iClient)+iTime):iTime, true); - - if(iTime) - { - Keys_GetTimeFromStamp(sParam, sizeof(sParam), iTime, iClient); - } - else - { - FormatEx(sParam, sizeof(sParam), "%T", "FOREVER", iClient); - } - - PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "USE_KEY_EXT", sParam); - - return true; - } - - if(!VIP_IsValidVIPGroup(sParam)) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_GROUP", iClient); - return false; - } - - decl String:sClientGroup[64]; - VIP_GetClientVIPGroup(iClient, sClientGroup, sizeof(sClientGroup)); - if(!strcmp(sClientGroup, sParam)) - { - FormatEx(sError, iErrLen, "%T", "ERROR_ALREADY_VIP_GROUP", iClient); - return false; - } - - VIP_SetClientVIPGroup(iClient, sParam, true); - PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "USE_KEY_GRP_CNG", sParam); - - return true; -} - -public OnKeyPrint(iClient, const String:sKeyType[], Handle:hParamsArr, String:sBuffer[], iBufLen) -{ - decl String:sParam[KEYS_MAX_LENGTH]; - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - if(!strcmp(sKeyType, g_sKeyType[0])) - { - decl iTime, String:sTime[32]; - GetArrayString(hParamsArr, 1, sTime, sizeof(sTime)); - iTime = StringToInt(sTime); - if(iTime) - { - Keys_GetTimeFromStamp(sTime, sizeof(sTime), iTime, iClient); - } - else - { - FormatEx(sTime, sizeof(sTime), "%T", "FOREVER", iClient); - } - - FormatEx(sBuffer, iBufLen, "%T: %s\t%T: %s", "VIP_GROUP", iClient, sParam, "TERM", iClient, sTime); - - return; - } - - if(!strcmp(sKeyType, g_sKeyType[1])) - { - decl iTime, String:sTime[32]; - iTime = StringToInt(sParam); - if(iTime) - { - Keys_GetTimeFromStamp(sTime, sizeof(sTime), iTime, iClient); - } - else - { - FormatEx(sTime, sizeof(sTime), "%T", "FOREVER", iClient); - } - - FormatEx(sBuffer, iBufLen, "%T: %s", "TERM", iClient, sTime); - - return; - } - - FormatEx(sBuffer, iBufLen, "%T: %s", "VIP_GROUP", iClient, sParam); -} diff --git a/addons/sourcemod/scripting/Keys_WCS.sp b/addons/sourcemod/scripting/Keys_WCS.sp deleted file mode 100644 index f13c0a7..0000000 --- a/addons/sourcemod/scripting/Keys_WCS.sp +++ /dev/null @@ -1,137 +0,0 @@ -#pragma semicolon 1 - -#include -#include -#include - -public Plugin:myinfo = -{ - name = "[Keys] WCS", - author = "R1KO", - version = "1.0", - url = "hlmod.ru" -}; - -new const String:g_sKeyType[][] = {"wcs_gold", "wcs_p_race", "wcs_bank_lvl"}; - -public OnPluginStart() -{ - LoadTranslations("keys_core.phrases"); - LoadTranslations("keys_wcs_module.phrases"); - - if (Keys_IsCoreStarted()) Keys_OnCoreStarted(); -} - -public OnPluginEnd() -{ - for(new i = 0; i < sizeof(g_sKeyType); ++i) - { - Keys_UnregKey(g_sKeyType[i]); - } -} - -public Keys_OnCoreStarted() -{ - for(new i = 0; i < sizeof(g_sKeyType); ++i) - { - Keys_RegKey(g_sKeyType[i], OnKeyParamsValidate, OnKeyUse, OnKeyPrint); - } -} - -public bool:OnKeyParamsValidate(iClient, const String:sKeyType[], Handle:hParamsArr, String:sError[], iErrLen) -{ - if(GetArraySize(hParamsArr) != 1) - { - FormatEx(sError, iErrLen, "%T", "ERROR_NUM_ARGS", iClient); - return false; - } - - decl String:sParam[KEYS_MAX_LENGTH]; - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - - if(!strcmp(sKeyType, g_sKeyType[1])) - { - if(!WCS_IsRacePrivate(sParam)) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_RACE", iClient); - return false; - } - - return true; - } - - if(StringToInt(sParam) < 1) - { - FormatEx(sError, iErrLen, "%T", !strcmp(sKeyType, g_sKeyType[0]) ? "ERROR_INVALID_AMONUT":"ERROR_INVALID_LVL", iClient); - return false; - } - - return true; -} - -public bool:OnKeyUse(iClient, const String:sKeyType[], Handle:hParamsArr, String:sError[], iErrLen) -{ - decl String:sParam[KEYS_MAX_LENGTH]; - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - - if(!strcmp(sKeyType, g_sKeyType[0])) - { - if(!WCS_GiveGold(iClient, StringToInt(sParam))) - { - FormatEx(sError, iErrLen, "%T", "ERROR_HAS_OCCURRED", iClient); - return false; - } - - PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "YOU_RECEIVED_GOLD", StringToInt(sParam)); - return true; - } - - if(!strcmp(sKeyType, g_sKeyType[2])) - { - if(!WCS_GiveLBlvl(iClient, StringToInt(sParam))) - { - FormatEx(sError, iErrLen, "%T", "ERROR_HAS_OCCURRED", iClient); - return false; - } - - PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "YOU_RECEIVED_BLVL", StringToInt(sParam)); - return true; - } - - if(!WCS_IsRacePrivate(sParam)) - { - FormatEx(sError, iErrLen, "%T", "ERROR_INVALID_RACE", iClient); - return false; - } - - decl String:sAuth[32]; - GetClientAuthId(iClient, AuthId_Steam2, sAuth, sizeof(sAuth)); - if(!WCS_GivePrivateRace(sAuth, sParam)) - { - FormatEx(sError, iErrLen, "%T", "ERROR_HAS_OCCURRED", iClient); - return false; - } - - PrintToChat(iClient, "%t%t", "CHAT_PREFIX", "YOU_RECEIVED_PRIVATE_RACE", sParam); - - return true; -} - -public OnKeyPrint(iClient, const String:sKeyType[], Handle:hParamsArr, String:sBuffer[], iBufLen) -{ - decl String:sParam[KEYS_MAX_LENGTH]; - GetArrayString(hParamsArr, 0, sParam, sizeof(sParam)); - if(!strcmp(sKeyType, g_sKeyType[0])) - { - FormatEx(sBuffer, iBufLen, "%T: %s", "GOLD", iClient, sParam); - return; - } - - if(!strcmp(sKeyType, g_sKeyType[1])) - { - FormatEx(sBuffer, iBufLen, "%T: %s", "PRIVATE_RACE", iClient, sParam); - return; - } - - FormatEx(sBuffer, iBufLen, "%T: %s", "BLVL", iClient, sParam); -} diff --git a/addons/sourcemod/scripting/include/keys_core.inc b/addons/sourcemod/scripting/include/keys_core.inc deleted file mode 100644 index b8dafbe..0000000 --- a/addons/sourcemod/scripting/include/keys_core.inc +++ /dev/null @@ -1,121 +0,0 @@ -#if defined _keys_core_included - #endinput -#endif -#define _keys_core_included - -#define KEYS_MAX_LENGTH 64 - -// Прототип вызова при валидации параметров ключа -functag public bool:KeyParamsValidateCallback(iClient, const String:sKeyType[], Handle:hParamsArr, String:sError[], iErrLen); - -// Прототип вызова при акцивации ключа -functag public bool:KeyUseCallback(iClient, const String:sKeyType[], Handle:hParamsArr, String:sError[], iErrLen); - -// Прототип вызова при выводе параметров ключа -functag public KeyPrintCallback(iClient, const String:sKeyType[], Handle:hParamsArr, String:sBuffer[], iBufLen); - -// Вызывается когда ядро было загружено -forward Keys_OnCoreStarted(); - -// Загружено ли ядро -native bool:Keys_IsCoreStarted(); - -// Получает Handle базы данных -native Handle:Keys_GetCoreDatabase(); - -// Регистрирует тип ключей -native bool:Keys_RegKey(const String:sKeyType[], - KeyParamsValidateCallback:OnKeyParamsValidate, - KeyUseCallback:OnKeyUse, - KeyPrintCallback:OnKeyPrint); - -// Разрегистрирует тип ключей -native Keys_UnregKey(const String:sKeyType[]); - -// Для использования не забыть: -// LoadTranslations("keys_core.phrases"); -stock Keys_GetTimeFromStamp(String:sBuffer[], iMaxLength, iTimeStamp, iClient = LANG_SERVER) -{ - if (iTimeStamp > 31536000) - { - new iYears = iTimeStamp / 31536000; - new i = iTimeStamp - (iYears*31536000); - if(i > 2592000) - { - FormatEx(sBuffer, iMaxLength, "%d %T %d %T", iYears, "YEARS", iClient, i / 2592000, "MONTHS", iClient); - } - else - { - FormatEx(sBuffer, iMaxLength, "%d %T", iYears, "YEARS", iClient); - } - return; - } - - if (iTimeStamp > 2592000) - { - new iMonths = iTimeStamp / 2592000; - new i = iTimeStamp - (iMonths*2592000); - if (i > 86400) - { - FormatEx(sBuffer, iMaxLength, "%d %T %d %T", iMonths, "MONTHS", iClient, i / 86400, "DAYS", iClient); - } - else - { - FormatEx(sBuffer, iMaxLength, "%d %T", iMonths, "MONTHS", iClient); - } - return; - } - - if (iTimeStamp > 86400) - { - new iDays = iTimeStamp / 86400 % 365; - new iHours = (iTimeStamp / 3600) % 24; - if (iHours > 0) - { - FormatEx(sBuffer, iMaxLength, "%d %T %d %T", iDays, "DAYS", iClient, iHours, "HOURS", iClient); - } - else - { - FormatEx(sBuffer, iMaxLength, "%d %T", iDays, "DAYS", iClient); - } - return; - } - - new iHours = (iTimeStamp / 3600); - new iMins = (iTimeStamp / 60) % 60; - new iSecs = iTimeStamp % 60; - - if (iHours > 0) - { - FormatEx(sBuffer, iMaxLength, "%02d:%02d:%02d", iHours, iMins, iSecs); - } - else - { - FormatEx(sBuffer, iMaxLength, "%02d:%02d", iMins, iSecs); - } -} - -public SharedPlugin:__pl_keys_core= -{ - name = "keys_core", - file = "Keys_Core.smx", -#if defined REQUIRE_PLUGIN - required = 1 -#else - required = 0 -#endif -}; - -#if !defined REQUIRE_PLUGIN -<<<<<<< HEAD -public void __pl_keys_core_SetNTVOptional() -======= -public __pl_keys_core_SetNTVOptional() ->>>>>>> 4ee67050d3fb25df6e30b26e03301ee38d46b425 -{ - MarkNativeAsOptional("Keys_IsCoreStarted"); - MarkNativeAsOptional("Keys_GetCoreDatabase"); - MarkNativeAsOptional("Keys_RegKey"); - MarkNativeAsOptional("Keys_UnregKey"); -} -#endif diff --git a/addons/sourcemod/scripting/include/store.inc b/addons/sourcemod/scripting/include/store.inc deleted file mode 100644 index 057fcf9..0000000 --- a/addons/sourcemod/scripting/include/store.inc +++ /dev/null @@ -1,100 +0,0 @@ -#if defined _store_included - #endinput -#endif -#define _store_included - -new g_cvarChatTag = -1; -#define CHAT_TAG g_eCvars[g_cvarChatTag][sCache] - -#define ITEM_NAME_LENGTH 64 -#define STORE_MAX_ITEMS 2048 -#define STORE_MAX_HANDLERS 64 -#define STORE_MAX_PLANS 8 -#define STORE_MAX_SLOTS 4 - -enum Item_Plan -{ - String:szName[ITEM_NAME_LENGTH], - iPrice, - iTime -} - -enum Store_Item -{ - String:szName[ITEM_NAME_LENGTH], - String:szUniqueId[PLATFORM_MAX_PATH], - String:szShortcut[64], - iId, - iPrice, - iParent, - iHandler, - iFlagBits, - iData, - iPlans, - bool:bBuyable, - bool:bIgnoreVIP, - Handle:hAttributes -} - -enum Type_Handler -{ - String:szType[64], - String:szUniqueKey[32], - bool:bEquipable, - bool:bRaw, - Handle:hPlugin, - Function:fnMapStart, - Function:fnReset, - Function:fnConfig, - Function:fnUse, - Function:fnRemove -} - -enum Client_Item -{ - iId, - iUniqueId, - bool:bSynced, - bool:bDeleted, - iDateOfPurchase, - iDateOfExpiration, - iPriceOfPurchase, -} - -native Store_RegisterHandler(String:type[], String:uniquekey[], Function:mapstart, Function:reset, Function:config, Function:use, Function:remove, bool:equipable = true, bool:raw = false); -native Store_RegisterMenuHandler(String:identifier[], Function:menu, Function:handler); -native Store_SetDataIndex(itemid, index); -native Store_GetDataIndex(itemid); -native Store_GetEquippedItem(client, String:type[], slot=0); -native Store_IsClientLoaded(client); -native Store_DisplayPreviousMenu(client); -native Store_SetClientMenu(client, num); -native Store_GetClientCredits(client); -native Store_SetClientCredits(client, credits); -native Store_IsClientVIP(client); -native Store_IsItemInBoughtPackage(client, itemid, uid=-1); -native Store_ShouldConfirm(); -native Store_DisplayConfirmMenu(client, String:title[], Function:callback, data); -native Store_GetItem(itemid, output[Store_Item]); -native Store_GetHandler(index, output[Type_Handler]); -native Store_GiveItem(client, itemid, purchase=0, expiration=0, price=0); -native Store_RemoveItem(client, itemid); -native Store_GetClientItem(client, itemid, output[Client_Item]); -native Store_GetClientTarget(client); -native Store_GiveClientItem(client, recipient, itemid); -native Store_HasClientItem(client, itemid); -native Store_IterateEquippedItems(client, &start, bool:attributes=false); - -forward Store_OnClientModelChanged(client, String:model[]); - -public Extension:__ext_store_sm = -{ - name = "Store - The Resurrection", - file = "store_sm.ext", -#if defined AUTOLOAD_EXTENSIONS - autoload = 1, -#else - autoload = 0, -#endif - required = 0, -}; \ No newline at end of file diff --git a/addons/sourcemod/scripting/include/wcs.inc b/addons/sourcemod/scripting/include/wcs.inc deleted file mode 100644 index 29f6c8d..0000000 --- a/addons/sourcemod/scripting/include/wcs.inc +++ /dev/null @@ -1,553 +0,0 @@ -#if defined _wcs_included - #endinput -#endif -#define _wcs_included - -/** - * GetRealSpeed, GetRealGravity, GetRealAlpha, GetRealHealth - * , . - * GetRealModel , - * . - */ - -/** - * Get client's Anti Ultimate Status. - * - * @param index An integer. - * @return Anti Ultimate Status. - */ -native bool:WCS_GetAntiUlt(index); - -/** - * Get client's Anti Aura Status. - * - * @param index An integer. - * @return Anti Aura Status. - */ -native bool:WCS_GetAntiAura(index); - -/** - * Get client's Anti Totem Status. - * - * @param index An integer. - * @return Anti Totem Status. - */ -native bool:WCS_GetAntiTotem(index); - -/** - * Get client's 'Hide Effects' opt Status. - * - * @param index An integer. - * @return Hide Effects opt Status. - */ -native bool:WCS_GetHideEffects(index); - -/** - * Get client's 'Mute Sound' opt Status. - * - * @param index An integer. - * @return Mute Sound opt Status. - */ -native bool:WCS_GetMuteSound(index); - -/** - * Get client's 'Hide Skill Msg' opt Status. - * - * @param index An integer. - * @return Hide Skill Msg opt Status. - */ -native bool:WCS_GetHideSkillMsg(index); - -/** - * Get client's gold. - * - * @param index An integer. - * @return Client's gold. - */ -native WCS_GetGold(index); - -/** - * Get client's lvl. - * - * @param index An integer. - * @return Client's lvl. - */ -native WCS_GetLvl(index); - -/** - * Get client's race lvl. - * - * @param index An integer. - * @return Client's race lvl. - */ -native WCS_GetCLvl(index); - -/** - * Get client's Level Bank lvl. - * - * @param index An integer. - * @return Client's Level Bank lvl. - */ -native WCS_GetLBlvl(index); - -/** - * Get client's vip status. - * - * @param index An integer. - * @return true on success, false otherwise. - */ -native bool:WCS_GetVip(index); - -/** - * Get client's reborn status. - * - * @param index An integer. - * @return true on success, false otherwise. - */ -native bool:WCS_GetReborn(index); - -/** - * Get client's xp. - * - * @param index An integer. - * @return Client's xp. - */ -native WCS_GetXp(index); - -/** - * Get client's xp difference. - * - * @param index An integer. - * @return Client's xp. - */ -native WCS_GetXpDifference(index); - -/** - * Get client's race name. - * - * @param index An integer. - * @param race An string. - * @params size An integer. - * @return true on success. - */ -native bool:WCS_GetRace(index, String:race[], size); - -/** - * Get client's real speed. - * - * @param index An integer. - * @return Client's speed. - */ -native Float:WCS_GetRealSpeed(index); - -/** - * Get client's real gravity. - * - * @param index An integer. - * @return Client's speed. - */ -native Float:WCS_GetRealGravity(index); - -/** - * Get client's real alpha. - * - * @param index An integer. - * @return Client's alpha. - */ -native WCS_GetRealAlpha(index); - -/** - * Get client's real health. - * - * @param index An integer. - * @return Client's health. - */ -native WCS_GetRealHealth(index); - -/** - * Get client's real model. - * - * @param index An integer. - * @param model An string. - * @param size An integer. - * @return true on success, false otherwise. - */ -native bool:WCS_GetRealModel(index, String:model[], size); - -/** - * Get random client between radius. - * - * @param client An integer. - * @param radius An float. - * @param checkImmun An bool. - * @return random client on true. - */ -native WCS_GetRandomPosition(client, Float:radius, bool:checkImmun); - -/** - * Get nearest client between radius. - * - * @param client An integer. - * @param radius An float. - * @param checkImmun An bool. - * @return nearest client on true. - */ -native WCS_GetBestPosition(client, Float:radius, bool:checkImmun); - -/** - * Get nearest client to aim with radius. - * - * @param client An integer. - * @param distance An float. (0.0 - ) - * @param radius An float. - * @param checkImmun An bool. - * @return nearest client on true. - */ -native WCS_GetNearAim(client, Float:distance = 0.0, Float:radius, bool:checkImmun); - -/** - * Get client is admin. - * - * @param client An integer. - * @return true if client is admin, false otherwise. - */ -native bool:WCS_GetWcsAdmin(client); - -/** - * Init Effects to client & attacker [optional]. - * If you want to use effect only for client: - * InitEffects(client, client, effect); - * - * @param client An integer. - * @param victim An integer. - * @param effect An string. - * @return true on success. - */ -native bool:WCS_InitEffects(client, victim, const String:effect[]); - -/** - * Give client gold. - * - * @param client An integer. - * @param value An integer. - * @return true on success. - */ -native bool:WCS_GiveGold(client, value); - -/** - * Give client lvl. - * - * @param client An integer. - * @param value An integer. - * @return true on success. - */ -native bool:WCS_GiveLvl(client, value); - -/** - * Give client race lvl. - * - * @param client An integer. - * @param value An integer. - * @return true on success. - */ -native bool:WCS_GiveCLvl(client, value); - -/** - * Give client Level Bank lvl. - * - * @param client An integer. - * @param value An integer. - * @return true on success. - */ -native bool:WCS_GiveLBlvl(client, value); - -/** - * Give client xp. - * - * @param client An integer. - * @param value An integer. - * @param announce An bool. - * @return true on success. - */ -native bool:WCS_GiveXp(client, value, bool:announce = true); - -/** - * Take client gold. - * - * @param client An integer. - * @param value An integer. - * @return true on success. - */ -native bool:WCS_TakeGold(client, value); - -/** - * Take client Level Bank lvl. - * - * @param client An integer. - * @param value An integer. - * @return true on success. - */ -native bool:WCS_TakeLBlvl(client, value); - -/** - * Set client real speed. - * - * @param client An integer. - * @param value An float. - * @return true on success. - */ -native bool:WCS_SetRealSpeed(client, Float:value); - -/** - * Set client real gravity. - * - * @param client An integer. - * @param value An float. - * @return true on success. - */ -native bool:WCS_SetRealGravity(client, Float:value); - -/** - * Set client real alpha. - * - * @param client An integer. - * @param value An integer. - * @return true on success, false otherwise. - */ -native bool:WCS_SetRealAlpha(client, value); - -/** - * Set client real health. - * - * @param client An integer. - * @param value An integer. - * @return true on success, false otherwise. - */ -native bool:WCS_SetRealHealth(client, value); - -/** - * Set client's real model. - * - * @param index An integer. - * @param model An string. - * @return true on success, false otherwise. - */ -native bool:WCS_SetRealModel(index, const String:model[]); - -/** - * Set client's race. - * - * @param index An integer. - * @param race An String. - * @param suicide An bool. (Check or not CVAR 'wcs_cr_suicide' = 1 then client will be killed) - * @return true on success, false otherwise. - */ -native bool:WCS_SetRace(index, const String:race[], bool:suicide = true); - -/** - * Reset client's skills. - * - * @param index An integer. - * @param fully An bool. (if true then dont reuse skills after this operation) - * @return true on success, false otherwise. - */ -native bool:WCS_ResetSkills(client, bool:fully); - -/** - * Reset client ultimate cooldown. - * - * @param client An integer. - * @return true on success. - */ -native bool:WCS_ResetUltCld(client); - -/** - * Reset client ability cooldown. - * - * @param client An integer. - * @return true on success, false otherwise. - */ -native bool:WCS_ResetAbilityCld(client); - -/** - * Checks if the race is private - * - * @param racename An string. [64] - * @return true on success, false otherwise. - */ -native bool:WCS_IsRacePrivate(const String:RaceName[]); - -/** - * Gives a private race to client - * - * @param steamid An string. [64] - * @param racename An string. [64] - * @return true on success, false otherwise. - */ -native bool:WCS_GivePrivateRace(const String:SteamId[], const String:RaceName[]); - -/** - * Take a private race from client - * - * @param steamid An string. [64] - * @param racename An string. [64] - * @return true on success, false otherwise. - */ -native bool:WCS_TakePrivateRace(const String:SteamId[], const String:RaceName[]); - -/** - * Get required lvl for race - * - * @param racename An string. [64] - * @return required lvl on success, -1 otherwise. - */ -native WCS_GetRaceReqLvl(const String:RaceName[]); - -/** - * Get client's totems count that he can use (every use totem this value will decreased and restored on special events [this value = GetClientTotemsMax on special events]) - * - * @param client An integer. - * @return Amount of totems. - */ -native WCS_GetClientTotems(client); - -/** - * Get client's totems count maximum - * - * @param client An integer. - * @return Amount of maximum totems. - */ -native WCS_GetClientTotemsMax(client); - -/** - * Get client's vip group. - * - * @param client An integer. - * @param group An string. - * @params size An integer. - * @return true on success. - */ -native bool:WCS_GetVipGroup(client, String:group[], size); - -/** - * Get client's vip premium status. - * - * @param client An integer. - * @return true on success, false otherwise. - */ -native bool:WCS_GetVipPremium(client); - -/** - * Called on client skill lvl up - * - */ -forward WCS_OnSkillLvlUp(client, skilllvl, const String:skillname[]); - -/** - * Called on client lvl up - * - */ -forward WCS_OnLvlUp(client, lvl); - -/** - * Called on client ultimate cooldown has finished - * - */ -forward WCS_OnUltimateCld(client); - -/** - * Called on client ability cooldown has finished - * - */ -forward WCS_OnAbilityCld(client); - -/** - * Called on client skills has resetted - * - */ -forward WCS_OnSkillsReset(client, bool:fully); - -/** - * Called on client xp gain - * - */ -forward WCS_OnXpGain(client, xp, bool:lvlup); - -/** - * Called on client gold gain - * - */ -forward WCS_OnGoldGain(client, gold); - -/** - * Called on client ultimate pre - * - */ -forward Action:WCS_OnUltimatePre(client, const String:ultimate[]); - -/** - * Called on client ultimate post - * - */ -forward WCS_OnUltimatePost(client); - -/** - * Called on client ability pre - * - */ -forward Action:WCS_OnAbilityPre(client, const String:ability[]); - -/** - * Called on client ability post - * - */ -forward WCS_OnAbilityPost(client); - -/** - * Called on client change race pre - * - */ -forward Action:WCS_OnRaceChangePre(client, const String:OldRace[], const String:NewRace[]); - -/** - * Called on client change race post - * - */ -forward WCS_OnRaceChangePost(client); - -/** - * Called on client item purchase pre - * - * PaymentType -- "cash" "gold" - */ -forward Action:WCS_OnItemPurchasePre(client, const String:ItemName[], const String:BlockName[], ItemCost, const String:PaymentType[]); - -/** - * Called on client item purchase post - * - */ -forward WCS_OnItemPurchasePost(client); - -/** - * Called on client skills just set pre - * - */ -forward Action:WCS_OnSkillsSetPre(client, const String:Race[]); - -/** - * Called on client skills just set - * - */ -forward WCS_OnSkillsSet(client, const String:Race[]); - -/** - * Called on client loaded - * - */ -forward WCS_OnClientLoaded(client); - -/** - * Called on race should show - * - */ -forward Action:WCS_OnRaceShouldShow(client, const String:Race[], ReqLvl); \ No newline at end of file diff --git a/addons/sourcemod/scripting/keys/api.sp b/addons/sourcemod/scripting/keys/api.sp deleted file mode 100644 index cbd21af..0000000 --- a/addons/sourcemod/scripting/keys/api.sp +++ /dev/null @@ -1,82 +0,0 @@ - -static Handle:g_hGlobalForward_OnCoreStarted; - -public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) -{ - MarkNativeAsOptional("GetClientAuthId"); - MarkNativeAsOptional("GetClientAuthString"); - - g_hGlobalForward_OnCoreStarted = CreateGlobalForward("Keys_OnCoreStarted", ET_Ignore); - - CreateNative("Keys_IsCoreStarted", Native_IsCoreStarted); - CreateNative("Keys_GetCoreDatabase", Native_GetCoreDatabase); - CreateNative("Keys_RegKey", Native_RegKey); - CreateNative("Keys_UnregKey", Native_UnregKey); - - /* - CreateNative("Keys_GenerateKey", Native_GenerateKey); - CreateNative("Keys_AddKey", Keys_AddKey); - CreateNative("Keys_RemoveKey", Keys_RemoveKey); - CreateNative("Keys_IsValidKey", Native_IsValidKey); - */ - - RegPluginLibrary("keys_core"); - - return APLRes_Success; -} - -CreateForward_OnCoreStarted() -{ - Call_StartForward(g_hGlobalForward_OnCoreStarted); - Call_Finish(); -} - -public Native_IsCoreStarted(Handle:hPlugin, iNumParams) -{ - return g_bIsStarted; -} - -public Native_GetCoreDatabase(Handle:hPlugin, iNumParams) -{ - return _:CloneHandle(g_hDatabase, hPlugin); -} - -public Native_RegKey(Handle:hPlugin, iNumParams) -{ - decl String:sKeyType[KEYS_MAX_LENGTH]; - GetNativeString(1, sKeyType, sizeof(sKeyType)); - - if(FindStringInArray(g_hKeysArray, sKeyType) != -1) - { - ThrowNativeError(SP_ERROR_NATIVE, "Тип ключа \"%s\" уже зарегистрирован!", sKeyType); - return false; - } - - new Handle:hDataPack = CreateDataPack(); - WritePackCell(hDataPack, hPlugin); - WritePackCell(hDataPack, GetNativeCell(2)); - WritePackCell(hDataPack, GetNativeCell(3)); - WritePackCell(hDataPack, GetNativeCell(4)); - - SetTrieValue(g_hKeysTrie, sKeyType, hDataPack); - PushArrayString(g_hKeysArray, sKeyType); - - return true; -} - -public Native_UnregKey(Handle:hPlugin, iNumParams) -{ - decl String:sKeyType[KEYS_MAX_LENGTH], index; - GetNativeString(1, sKeyType, sizeof(sKeyType)); - - if((index = FindStringInArray(g_hKeysArray, sKeyType)) != -1) - { - RemoveFromArray(g_hKeysArray, index); - decl Handle:hDataPack; - if(GetTrieValue(g_hKeysTrie, sKeyType, hDataPack)) - { - CloseHandle(hDataPack); - } - RemoveFromTrie(g_hKeysTrie, sKeyType); - } -} diff --git a/addons/sourcemod/scripting/keys/cmds.sp b/addons/sourcemod/scripting/keys/cmds.sp deleted file mode 100644 index 2ec5bd1..0000000 --- a/addons/sourcemod/scripting/keys/cmds.sp +++ /dev/null @@ -1,1000 +0,0 @@ -#define GET_UID(%0) (%0 == 0 ? 0:UID(%0)) - -GET_CID(iClient) -{ - if(iClient) - { - iClient = CID(iClient); - if(!iClient) - { - return -1; - } - - return iClient; - } - - return 0; -} - -RegAdminCmds() -{ - // CMD`s for use keys - RegConsoleCmd("key", UseKey_CMD); - RegConsoleCmd("usekey", UseKey_CMD); - - // CMD`s for create keys - RegAdminCmd("key_add", AddKey_CMD, ADMFLAG_ROOT); - RegAdminCmd("key_create", AddKey_CMD, ADMFLAG_ROOT); - RegAdminCmd("keys_gen", AddKey_CMD, ADMFLAG_ROOT); - - // CMD`s for remove keys - RegAdminCmd("key_del", DelKey_CMD, ADMFLAG_ROOT); - RegAdminCmd("key_rem", DelKey_CMD, ADMFLAG_ROOT); - RegAdminCmd("keys_clear", ClearKeys_CMD, ADMFLAG_ROOT); - - // CMD`s for keys output - RegAdminCmd("keys_list", KeysListDump_CMD, ADMFLAG_ROOT); - RegAdminCmd("keys_dump", KeysListDump_CMD, ADMFLAG_ROOT); -} - -public Action:UseKey_CMD(iClient, iArgs) -{ - if (iClient) - { - new ReplySource:CmdReplySource = GetCmdReplySource(); - - if(g_CVAR_iAttempts && g_bIsBlocked[iClient]) - { - if(g_iAttempts[iClient] > GetTime()) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_BLOCKED"); - return Plugin_Handled; - - } - else - { - UnBlockClient(iClient); - g_bIsBlocked[iClient] = false; - g_iAttempts[iClient] = 0; - } - } - - if(iArgs != 1) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "USAGE_ERROR_USE_KEY"); - return Plugin_Handled; - } - - decl String:sKey[KEYS_MAX_LENGTH], String:sQuery[512]; - GetCmdArg(1, SZF(sKey)); - - if(!UTIL_ValidateKey(sKey, strlen(sKey), SZF(sQuery))) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", sQuery); - - if(g_CVAR_iAttempts) - { - if(g_iAttempts[iClient]++ >= g_CVAR_iAttempts) - { - BlockClient(iClient); - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_BLOCKED"); - return Plugin_Handled; - } - - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_KEY_LEFT", g_CVAR_iAttempts-g_iAttempts[iClient]); - } - else - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_KEY"); - } - - return Plugin_Handled; - } - - decl Handle:hDP, String:sAuth[32]; - hDP = CreateDataPack(); - WritePackCell(hDP, UID(iClient)); - WritePackCell(hDP, CmdReplySource); - - GetClientAuthId(iClient, AuthId_Engine, SZF(sAuth)); - if (g_bDBMySQL) - { - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "SELECT `key_name`, `type`, `expires`, `uses`, IF((SELECT `key_name` FROM `keys_players_used` WHERE `auth` = '%s' AND `key_name` = '%s') IS NULL, 0, 1) as `used`, `param1`, `param2`, `param3`, `param4`, `param5` FROM `table_keys` WHERE `key_name` = '%s' LIMIT 1;", sAuth, sKey, sKey); - } - else - { - FormatEx(SZF(sQuery), "SELECT `key_name`, `type`, `expires`, `uses`, IF((SELECT `key_name` FROM `keys_players_used` WHERE `auth` = '%s' AND `key_name` = '%s') IS NULL, 0, 1) as `used`, `param1`, `param2`, `param3`, `param4`, `param5` FROM `table_keys` WHERE `key_name` = '%s' AND `sid` = %d LIMIT 1;", sAuth, sKey, sKey, g_iServerID); - } - } - else - { - FormatEx(SZF(sQuery), "SELECT `key_name`, `type`, `expires`, `uses`, CASE WHEN (SELECT `key_name` FROM `keys_players_used` WHERE `auth` = '%s' AND `key_name` = '%s') IS NULL THEN 0 ELSE 1 END AS `used`, `param1`, `param2`, `param3`, `param4`, `param5` FROM `table_keys` WHERE `key_name` = '%s' LIMIT 1;", sAuth, sKey, sKey); - } - - SQL_TQuery(g_hDatabase, SQL_Callback_UseKey, sQuery, hDP); - } - - return Plugin_Handled; -} - -public SQL_Callback_UseKey(Handle:hOwner, Handle:hResult, const String:sDBError[], any:hDP) -{ - if (hResult == INVALID_HANDLE || sDBError[0]) - { - CloseHandle(hDP); - LogError("SQL_Callback_UseKey: %s", sDBError); - return; - } - - ResetPack(hDP); - - new iClient = CID(ReadPackCell(hDP)); - new ReplySource:CmdReplySource = ReplySource:ReadPackCell(hDP); - CloseHandle(hDP); - - if (iClient) - { - if(SQL_FetchRow(hResult)) - { - decl Handle:hDataPack, String:sKeyType[KEYS_MAX_LENGTH]; - SQL_FetchString(hResult, 1, SZF(sKeyType)); - if(GetTrieValue(g_hKeysTrie, sKeyType, hDataPack)) - { - decl Handle:hPlugin, Function:fUseCallback, Handle:hParamsArr, String:sKey[KEYS_MAX_LENGTH], String:sParam[KEYS_MAX_LENGTH], String:sError[256], iExpires, iUses, i, bool:bResult; - SQL_FetchString(hResult, 0, SZF(sKey)); - - iExpires = SQL_FetchInt(hResult, 2); - if(iExpires) - { - if(iExpires < GetTime()) - { - DeleteKey(sKey); - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_KEY_NOT_EXIST"); - return; - } - } - - iUses = SQL_FetchInt(hResult, 3); - if(!iUses) - { - DeleteKey(sKey); - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_KEY_NOT_EXIST"); - return; - } - - if(SQL_FetchInt(hResult, 4)) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_KEY_ALREADY_USED"); - return; - } - - hParamsArr = CreateArray(ByteCountToCells(KEYS_MAX_LENGTH)); - for(i = 5; i < 10; ++i) - { - if(SQL_IsFieldNull(hResult, i)) - { - break; - } - - SQL_FetchString(hResult, i, SZF(sParam)); - PushArrayString(hParamsArr, sParam); - } - - SetPackPosition(hDataPack, DP_Plugin); - hPlugin = Handle:ReadPackCell(hDataPack); - - SetPackPosition(hDataPack, DP_OnUseCallback); - fUseCallback = Function:ReadPackCell(hDataPack); - - sError = "unknown"; - bResult = false; - Call_StartFunction(hPlugin, fUseCallback); - Call_PushCell(iClient); - Call_PushString(sKeyType); - Call_PushCell(hParamsArr); - Call_PushStringEx(SZF(sError), SM_PARAM_STRING_UTF8|SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); - Call_PushCell(sizeof(sError)); - Call_Finish(bResult); - - CloseHandle(hParamsArr); - - if(!bResult) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%s", "ERROR", sError); - return; - } - - decl String:sName[MAX_NAME_LENGTH], String:sAuth[32], String:sQuery[256]; - GetClientName(iClient, SZF(sName)); - GetClientAuthId(iClient, AuthId_Engine, SZF(sAuth)); - - if(--iUses) - { - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "INSERT INTO `keys_players_used` (`auth`, `key_name`) VALUES ('%s', '%s');", sAuth, sKey); - } - else - { - FormatEx(SZF(sQuery), "INSERT INTO `keys_players_used` (`auth`, `key_name`, `sid`) VALUES ('%s', '%s', %d);", sAuth, sKey, g_iServerID); - } - SQL_TQuery(g_hDatabase, SQL_Callback_ErrorCheck, sQuery); - - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "UPDATE `table_keys` SET `uses` = %d WHERE `key_name` = '%s';", iUses, sKey); - } - else - { - FormatEx(SZF(sQuery), "UPDATE `table_keys` SET `uses` = %d WHERE `key_name` = '%s' AND `sid` = %d;", iUses, sKey, g_iServerID); - } - SQL_TQuery(g_hDatabase, SQL_Callback_ErrorCheck, sQuery); - } - else - { - DeleteKey(sKey); - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "DELETE FROM `keys_players_used` WHERE `key_name` = '%s';", sKey); - } - else - { - FormatEx(SZF(sQuery), "DELETE FROM `keys_players_used` WHERE `key_name` = '%s' AND `sid` = %d;", sKey, g_iServerID); - } - SQL_TQuery(g_hDatabase, SQL_Callback_ErrorCheck, sQuery); - } - - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", "SUCCESS_USE_KEY", sKey); - LogToFile(g_sLogFile, "%T", "LOG_SUCCESS_USE_KEY", LANG_SERVER, sName, sAuth, sKey); - return; - } - - return; - } - - if(g_CVAR_iAttempts) - { - if(g_iAttempts[iClient]++ >= g_CVAR_iAttempts) - { - BlockClient(iClient); - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_BLOCKED"); - return; - } - - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_KEY_LEFT", g_CVAR_iAttempts-g_iAttempts[iClient]); - } - else - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_KEY"); - } - } -} - -public Action:AddKey_CMD(iClient, iArgs) -{ - new ReplySource:CmdReplySource = GetCmdReplySource(); - - if(iArgs < 5) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_NUM_ARGS"); - return Plugin_Handled; - } - - decl String:sKeyType[KEYS_MAX_LENGTH], Handle:hDataPack; - GetCmdArg(4, SZF(sKeyType)); - - if(!GetTrieValue(g_hKeysTrie, sKeyType, hDataPack)) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_TYPE"); - return Plugin_Handled; - } - - decl String:sKey[KEYS_MAX_LENGTH], String:sParam[KEYS_MAX_LENGTH], String:sError[256], iLifeTime, iUses, iCount, bool:bGen; - - GetCmdArg(0, SZF(sKey)); - - bGen = bool:(sKey[3] == 's'); - - if(bGen) - { - GetCmdArg(1, SZF(sParam)); - iCount = StringToInt(sParam); - if(iCount < 1) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_AMOUNT"); - return Plugin_Handled; - } - } - else - { - GetCmdArg(1, SZF(sKey)); - if(!UTIL_ValidateKey(sKey, strlen(sKey), SZF(sError))) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", sError); - return Plugin_Handled; - } - } - - GetCmdArg(2, SZF(sParam)); - iLifeTime = StringToInt(sParam); - if(iLifeTime < 0) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_LIFETIME"); - return Plugin_Handled; - } - - GetCmdArg(3, SZF(sParam)); - iUses = StringToInt(sParam); - if(iUses < 1) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_USES"); - return Plugin_Handled; - } - - decl Handle:hParamsArr, Handle:hPlugin, Function:FuncOnValidateParams, i, bool:bResult; - - hParamsArr = CreateArray(ByteCountToCells(KEYS_MAX_LENGTH)); - - for(i = 5; i <= iArgs; ++i) - { - GetCmdArg(i, SZF(sParam)); - PushArrayString(hParamsArr, sParam); - } - - SetPackPosition(hDataPack, DP_Plugin); - hPlugin = Handle:ReadPackCell(hDataPack); - - SetPackPosition(hDataPack, DP_OnValidateCallback); - FuncOnValidateParams = Function:ReadPackCell(hDataPack); - - sError = "unknown"; - bResult = false; - Call_StartFunction(hPlugin, FuncOnValidateParams); - Call_PushCell(iClient); - Call_PushString(sKeyType); - Call_PushCell(hParamsArr); - Call_PushStringEx(SZF(sError), SM_PARAM_STRING_UTF8|SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); - Call_PushCell(sizeof(sError)); - Call_Finish(bResult); - - if(!bResult) - { - CloseHandle(hParamsArr); - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%s", "ERROR", sError); - return Plugin_Handled; - } - - decl Handle:hDP, String:sQuery[256], iExpires; - - iClient = GET_UID(iClient); - iExpires = iLifeTime ? (iLifeTime + GetTime()):iLifeTime; - - if(bGen) - { - while(iCount > 0) - { - --iCount; - - UTIL_GenerateKey(sKey); - - hDP = CreateDataPack(); - WritePackCell(hDP, CloneArray(hParamsArr)); - WritePackString(hDP, sKey); - WritePackCell(hDP, false); - WritePackCell(hDP, iClient); - WritePackCell(hDP, CmdReplySource); - WritePackString(hDP, sKeyType); - WritePackCell(hDP, iUses); - WritePackCell(hDP, iExpires); - WritePackCell(hDP, iLifeTime); - - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "SELECT `expires` FROM `table_keys` WHERE `key_name` = '%s';", sKey); - } - else - { - FormatEx(SZF(sQuery), "SELECT `expires` FROM `table_keys` WHERE `key_name` = '%s' AND `sid` = %d;", sKey, g_iServerID); - } - SQL_TQuery(g_hDatabase, SQL_Callback_SearchKey, sQuery, hDP); - } - } - else - { - hDP = CreateDataPack(); - WritePackCell(hDP, CloneArray(hParamsArr)); - WritePackString(hDP, sKey); - WritePackCell(hDP, true); - WritePackCell(hDP, iClient); - WritePackCell(hDP, CmdReplySource); - WritePackString(hDP, sKeyType); - WritePackCell(hDP, iUses); - WritePackCell(hDP, iExpires); - WritePackCell(hDP, iLifeTime); - - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "SELECT `expires` FROM `table_keys` WHERE `key_name` = '%s';", sKey); - } - else - { - FormatEx(SZF(sQuery), "SELECT `expires` FROM `table_keys` WHERE `key_name` = '%s' AND `sid` = %d;", sKey, g_iServerID); - } - SQL_TQuery(g_hDatabase, SQL_Callback_SearchKey, sQuery, hDP); - } - - CloseHandle(hParamsArr); - - return Plugin_Handled; -} - -public SQL_Callback_SearchKey(Handle:hOwner, Handle:hResult, const String:sError[], any:hDP) -{ - ResetPack(hDP); - - new Handle:hParamsArr = Handle:ReadPackCell(hDP); - - if (hResult == INVALID_HANDLE || sError[0]) - { - LogError("SQL_Callback_SearchKey: %s", sError); - CloseHandle(hParamsArr); - CloseHandle(hDP); - return; - } - - decl String:sQuery[1024], String:sKey[KEYS_MAX_LENGTH], i; - ReadPackString(hDP, SZF(sKey)); - - if(SQL_FetchRow(hResult)) - { - if(ReadPackCell(hDP)) - { - i = GET_CID(ReadPackCell(hDP)); - if(i != -1) - { - UTIL_ReplyToCommand(i, ReplySource:ReadPackCell(hDP), "%t%t", "ERROR", "ERROR_KEY_ALREADY_EXISTS", sKey); - } - - CloseHandle(hParamsArr); - return; - } - else - { - decl Handle:hDP2; - hDP2 = CreateDataPack(); - WritePackCell(hDP2, hParamsArr); - UTIL_GenerateKey(sKey); - WritePackString(hDP2, sKey); // New Key - WritePackCell(hDP2, false); - i = ReadPackCell(hDP); // Client - WritePackCell(hDP2, i); - i = ReadPackCell(hDP); // CmdReplySource - WritePackCell(hDP2, i); - ReadPackString(hDP, SZF(sKey)); - WritePackString(hDP2, sKey); - i = ReadPackCell(hDP); // Uses - WritePackCell(hDP2, i); - i = ReadPackCell(hDP); // Expires - WritePackCell(hDP2, i); - i = ReadPackCell(hDP); // LifeTime - WritePackCell(hDP2, i); - CloseHandle(hDP); - - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "SELECT `expires` FROM `table_keys` WHERE `key_name` = '%s';", sKey); - } - else - { - FormatEx(SZF(sQuery), "SELECT `expires` FROM `table_keys` WHERE `key_name` = '%s' AND `sid` = %d;", sKey, g_iServerID); - } - SQL_TQuery(g_hDatabase, SQL_Callback_SearchKey, sQuery, hDP2); - } - - return; - } - - decl String:sBufferColumns[256], String:sBufferValues[256], String:sKeyType[KEYS_MAX_LENGTH], String:sParam[KEYS_MAX_LENGTH], iExpires, iUses; - - ReadPackCell(hDP); // ... - ReadPackCell(hDP); // Client - ReadPackCell(hDP); // CmdReplySource - - ReadPackString(hDP, SZF(sKeyType)); - - iUses = ReadPackCell(hDP); - iExpires = ReadPackCell(hDP); - - strcopy(SZF(sBufferColumns), "`param1`"); - GetArrayString(hParamsArr, 0, SZF(sParam)); - FormatEx(SZF(sBufferValues), "'%s'", sParam); - - for(i = 1; i < GetArraySize(hParamsArr); ++i) - { - Format(SZF(sBufferColumns), "%s, `param%d`", sBufferColumns, i+1); - GetArrayString(hParamsArr, i, SZF(sParam)); - Format(SZF(sBufferValues), "%s, '%s'", sBufferValues, sParam); - } - - SQL_FastQuery(g_hDatabase, "SET CHARSET 'utf8'"); - - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "INSERT INTO `table_keys` (`key_name`, `type`, `expires`, `uses`, %s) VALUES ('%s', '%s', %d, %d, %s);", sBufferColumns, sKey, sKeyType, iExpires, iUses, sBufferValues); - - } - else - { - FormatEx(SZF(sQuery), "INSERT INTO `table_keys` (`key_name`, `type`, `expires`, `uses`, `sid`, %s) VALUES ('%s', '%s', %d, %d, %d, %s);", sBufferColumns, sKey, sKeyType, iExpires, iUses, g_iServerID, sBufferValues); - - } - SQL_TQuery(g_hDatabase, SQL_Callback_AddKey, sQuery, hDP); -} - -public SQL_Callback_AddKey(Handle:hOwner, Handle:hResult, const String:sError[], any:hDP) -{ - ResetPack(hDP); - - new Handle:hParamsArr = Handle:ReadPackCell(hDP); - - if (hResult == INVALID_HANDLE || sError[0]) - { - LogError("SQL_Callback_AddKey: %s", sError); - CloseHandle(hParamsArr); - CloseHandle(hDP); - return; - } - - decl Handle:hDataPack, Handle:hPlugin, Function:fPrintCallback, String:sKey[KEYS_MAX_LENGTH], String:sKeyType[KEYS_MAX_LENGTH], String:sParams[512], String:sName[MAX_NAME_LENGTH], String:sAuth[32], String:sExpires[64], iLifeTime, iUses, iClient, ReplySource:CmdReplySource; - ReadPackString(hDP, SZF(sKey)); - ReadPackCell(hDP); - iClient = GET_CID(ReadPackCell(hDP)); - CmdReplySource = ReplySource:ReadPackCell(hDP); - - ReadPackString(hDP, SZF(sKeyType)); - - iUses = ReadPackCell(hDP); - ReadPackCell(hDP); - iLifeTime = ReadPackCell(hDP); - - if(iClient == -1) - { - iClient = 0; - } - - if(!iClient) - { - strcopy(SZF(sName), "CONSOLE"); - strcopy(SZF(sAuth), "STEAM_ID_SERVER"); - } - else - { - GetClientName(iClient, SZF(sName)); - GetClientAuthId(iClient, AuthId_Engine, SZF(sAuth)); - } - - if(iLifeTime) - { - Keys_GetTimeFromStamp(SZF(sExpires), iLifeTime, iClient); - } - else - { - FormatEx(SZF(sExpires), "%T", "FOREVER", iClient); - } - - sParams[0] = 0; - - GetTrieValue(g_hKeysTrie, sKeyType, hDataPack); - SetPackPosition(hDataPack, DP_Plugin); - hPlugin = Handle:ReadPackCell(hDataPack); - SetPackPosition(hDataPack, DP_OnPrintCallback); - fPrintCallback = Function:ReadPackCell(hDataPack); - Call_StartFunction(hPlugin, fPrintCallback); - Call_PushCell(LANG_SERVER); - Call_PushString(sKeyType); - Call_PushCell(hParamsArr); - Call_PushStringEx(SZF(sParams), SM_PARAM_STRING_UTF8|SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); - Call_PushCell(sizeof(sParams)); - Call_Finish(); - - if(SQL_GetAffectedRows(hOwner)) - { - if(iClient != -1) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", "SUCCESS_CREATE_KEY", sKey); - } - - LogToFile(g_sLogFile, "%T", "LOG_SUCCESS_CREATE_KEY", LANG_SERVER, sName, sAuth, sKey, sExpires, iUses, sKeyType, sParams); - } - else - { - if(iClient != -1) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_CREATE_KEY", sKey); - } - - LogToFile(g_sLogFile, "%T", "LOG_ERROR_CREATE_KEY", LANG_SERVER, sKey, sName, sAuth, sExpires, iUses, sKeyType, sParams); - } - - CloseHandle(hParamsArr); - CloseHandle(hDP); -} - -public Action:DelKey_CMD(iClient, iArgs) -{ - new ReplySource:CmdReplySource = GetCmdReplySource(); - - if(iArgs != 1) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_NUM_ARGS"); - return Plugin_Handled; - } - - decl String:sKey[KEYS_MAX_LENGTH], iLength; - GetCmdArg(1, SZF(sKey)); - - iLength = strlen(sKey); - if(iLength > KEYS_MAX_LENGTH || iLength < 8) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_KEY"); - return Plugin_Handled; - } - - DeleteKey(sKey, iClient, CmdReplySource); - - return Plugin_Handled; -} - -public SQL_Callback_RemoveKey(Handle:hOwner, Handle:hResult, const String:sError[], any:hDP) -{ - if (hResult == INVALID_HANDLE || sError[0]) - { - CloseHandle(hDP); - LogError("SQL_Callback_RemoveKey: %s", sError); - return; - } - - ResetPack(hDP); - - decl String:sKey[KEYS_MAX_LENGTH]; - ReadPackString(hDP, SZF(sKey)); - - if(ReadPackCell(hDP)) - { - decl iClient, String:sName[MAX_NAME_LENGTH], String:sAuth[32], ReplySource:CmdReplySource; - iClient = GET_CID(ReadPackCell(hDP)); - CmdReplySource = ReplySource:ReadPackCell(hDP); - - if(iClient == -1) - { - iClient = 0; - } - - if(!iClient) - { - strcopy(SZF(sName), "CONSOLE"); - strcopy(SZF(sAuth), "STEAM_ID_SERVER"); - } - else - { - GetClientName(iClient, SZF(sName)); - GetClientAuthId(iClient, AuthId_Engine, SZF(sAuth)); - } - - if(SQL_GetAffectedRows(hOwner)) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", "SUCCESS_REMOVE_KEY", sKey); - - LogToFile(g_sLogFile, "%T", "LOG_SUCCESS_REMOVE_KEY", LANG_SERVER, sKey, sName, sAuth); - } - else - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_REMOVE_KEY", sKey); - - LogToFile(g_sLogFile, "%T", "LOG_SUCCESS_REMOVE_KEY", LANG_SERVER, sKey, sName, sAuth); - } - } - else - { - if(SQL_GetAffectedRows(hOwner)) - { - LogToFile(g_sLogFile, "%T", "SUCCESS_REMOVE_KEY", LANG_SERVER, sKey); - } - else - { - LogToFile(g_sLogFile, "%T", "ERROR_REMOVE_KEY", LANG_SERVER, sKey); - } - } - - CloseHandle(hDP); -} - -public Action:ClearKeys_CMD(iClient, iArgs) -{ - new ReplySource:CmdReplySource = GetCmdReplySource(); - - decl String:sKeyType[64]; - if(iArgs == 1) - { - GetCmdArg(1, SZF(sKeyType)); - if(FindStringInArray(g_hKeysArray, sKeyType) == -1) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_INCORRECT_TYPE"); - return Plugin_Handled; - } - } - else - { - sKeyType[0] = 0; - } - - decl Handle:hDP, String:sQuery[256]; - hDP = CreateDataPack(); - WritePackCell(hDP, GET_UID(iClient)); - WritePackCell(hDP, CmdReplySource); - if(sKeyType[0]) - { - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "DELETE FROM `table_keys` WHERE `type` = '%s';", sKeyType); - } - else - { - FormatEx(SZF(sQuery), "DELETE FROM `table_keys` WHERE `type` = '%s' AND `sid` = %d;", sKeyType, g_iServerID); - } - WritePackCell(hDP, true); - WritePackString(hDP, sKeyType); - } - else - { - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "DELETE FROM `table_keys`;"); - } - else - { - FormatEx(SZF(sQuery), "DELETE FROM `table_keys` WHERE `sid` = %d;", g_iServerID); - } - } - - SQL_TQuery(g_hDatabase, SQL_Callback_RemoveKeys, sQuery, hDP); - - return Plugin_Handled; -} - -public SQL_Callback_RemoveKeys(Handle:hOwner, Handle:hResult, const String:sError[], any:hDP) -{ - if (hResult == INVALID_HANDLE || sError[0]) - { - LogError("SQL_Callback_RemoveKeys: %s", sError); - CloseHandle(hDP); - return; - } - - ResetPack(hDP); - - decl iClient, String:sKeyType[64], String:sName[MAX_NAME_LENGTH], String:sAuth[32], ReplySource:CmdReplySource; - iClient = GET_CID(ReadPackCell(hDP)); - CmdReplySource = ReplySource:ReadPackCell(hDP); - - if(iClient == -1) - { - iClient = 0; - } - - if(!iClient) - { - strcopy(SZF(sName), "CONSOLE"); - strcopy(SZF(sAuth), "STEAM_ID_SERVER"); - } - else - { - GetClientName(iClient, SZF(sName)); - GetClientAuthId(iClient, AuthId_Engine, SZF(sAuth)); - } - - if(IsPackReadable(hDP, 4)) - { - ReadPackCell(hDP); - ReadPackString(hDP, SZF(sKeyType)); - } - else - { - sKeyType[0] = 0; - } - - CloseHandle(hDP); - - if(SQL_GetAffectedRows(hOwner)) - { - if(sKeyType[0]) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", "SUCCESS_REMOVE_KEYS_TYPE", sKeyType); - LogToFile(g_sLogFile, "%T", "LOG_SUCCESS_REMOVE_KEYS_TYPE", LANG_SERVER, sKeyType, sName, sAuth); - } - else - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t", "SUCCESS_REMOVE_KEYS"); - LogToFile(g_sLogFile, "%T", "LOG_SUCCESS_REMOVE_KEYS", LANG_SERVER, sKeyType, sName, sAuth); - } - } - else - { - if(sKeyType[0]) - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_REMOVE_KEYS_TYPE", sKeyType); - LogToFile(g_sLogFile, "%T", "LOG_ERROR_REMOVE_KEYS_TYPE", LANG_SERVER, sKeyType, sName, sAuth); - } - else - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_REMOVE_KEYS"); - LogToFile(g_sLogFile, "%T", "LOG_ERROR_REMOVE_KEYS", LANG_SERVER, sKeyType, sName, sAuth); - } - } -} - -public Action:KeysListDump_CMD(iClient, iArgs) -{ - decl ReplySource:CmdReplySource, Handle:hDP, String:sQuery[512], iOffset, bool:bToFile; - CmdReplySource = GetCmdReplySource(); - - if(iArgs) - { - GetCmdArg(2, sQuery, 16); - iOffset = StringToInt(sQuery); - if(iOffset < 0) - { - iOffset = 0; - } - } - else - { - iOffset = 0; - } - - hDP = CreateDataPack(); - WritePackCell(hDP, GET_UID(iClient)); - WritePackCell(hDP, CmdReplySource); - GetCmdArg(0, sQuery, 32); - bToFile = sQuery[5] == 'd'; - WritePackCell(hDP, bToFile); - - if(!g_iServerID) - { - FormatEx(SZF(sQuery), "SELECT `key_name`, `type`, `expires`, `uses`, `param1`, `param2`, `param3`, `param4`, `param5` FROM `table_keys` ORDER BY `type`, `param1`, `param2`, `param3`, `param4`, `param5`, `expires`, `uses`;"); - } - else - { - FormatEx(SZF(sQuery), "SELECT `key_name`, `type`, `expires`, `uses`, `param1`, `param2`, `param3`, `param4`, `param5` FROM `table_keys` WHERE `sid` = %d ORDER BY `type`, `param1`, `param2`, `param3`, `param4`, `param5`, `expires`, `uses`;", g_iServerID); - } - - if(!bToFile) - { - sQuery[strlen(sQuery)-1] = 0; - Format(SZF(sQuery), "%s LIMIT %d, %d;", sQuery, iOffset, iClient ? 20:100); - } - - SQL_TQuery(g_hDatabase, SQL_Callback_SelectKeysList, sQuery, hDP); - - return Plugin_Handled; -} - -public SQL_Callback_SelectKeysList(Handle:hOwner, Handle:hResult, const String:sError[], any:hDP) -{ - if (hResult == INVALID_HANDLE || sError[0]) - { - CloseHandle(hDP); - LogError("SQL_Callback_SelectKeysList: %s", sError); - return; - } - - ResetPack(hDP); - decl iClient, ReplySource:CmdReplySource, bool:bToFile; - iClient = GET_CID(ReadPackCell(hDP)); - CmdReplySource = ReplySource:ReadPackCell(hDP); - bToFile = bool:ReadPackCell(hDP); - CloseHandle(hDP); - - if(!bToFile && iClient == -1) - { - return; - } - - if(SQL_GetRowCount(hResult) > 0) - { - decl String:sKey[64], String:sKeyType[64], String:sExpires[64], iUses, iCount, iTime, iExpires, i; - decl Handle:hFile, Handle:hDataPack, Handle:hPlugin, Function:fPrintCallback, Handle:hParamsArr, String:sParam[KEYS_MAX_LENGTH], String:sParams[512]; - - if(bToFile) - { - BuildPath(Path_SM, SZF(sParams), "data/keys_dump.txt"); - hFile = OpenFile(sParams, "w+"); - } - - iCount = 0; - iTime = GetTime(); - - while(SQL_FetchRow(hResult)) - { - SQL_FetchString(hResult, 1, SZF(sKeyType)); - - if(GetTrieValue(g_hKeysTrie, sKeyType, hDataPack)) - { - SQL_FetchString(hResult, 0, SZF(sKey)); - - iExpires = SQL_FetchInt(hResult, 2); - - if(iExpires) - { - if(iExpires < iTime) - { - DeleteKey(sKey); - continue; - } - - Keys_GetTimeFromStamp(SZF(sExpires), iExpires-iTime, iClient); - } - else - { - FormatEx(SZF(sExpires), "%T", "FOREVER", iClient); - } - - iUses = SQL_FetchInt(hResult, 3); - - if(!iUses) - { - DeleteKey(sKey); - continue; - } - - hParamsArr = CreateArray(ByteCountToCells(KEYS_MAX_LENGTH)); - - for(i = 4; i < 9; ++i) - { - if(SQL_IsFieldNull(hResult, i)) - { - break; - } - - SQL_FetchString(hResult, i, SZF(sParam)); - PushArrayString(hParamsArr, sParam); - } - - sParams[0] = 0; - - SetPackPosition(hDataPack, DP_Plugin); - hPlugin = Handle:ReadPackCell(hDataPack); - SetPackPosition(hDataPack, DP_OnPrintCallback); - fPrintCallback = Function:ReadPackCell(hDataPack); - Call_StartFunction(hPlugin, fPrintCallback); - Call_PushCell(iClient); - Call_PushString(sKeyType); - Call_PushCell(hParamsArr); - Call_PushStringEx(sParams, 256, SM_PARAM_STRING_UTF8|SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); - Call_PushCell(256); - Call_Finish(); - - CloseHandle(hParamsArr); - - if(bToFile) - { - WriteFileLine(hFile, "%d. %s\t\t%T: %12s\t\t%T: %4i\t\t%T: %s\t\t%s", ++iCount, sKey, "EXPIRES", iClient, sExpires, "USAGE_LEFT", iClient, iUses, "TYPE", iClient, sKeyType, sParams); - continue; - } - - UTIL_ReplyToCommand(iClient, CmdReplySource, "%d. %s\t\t%T: %12s\t\t%T: %4i\t\t%T: %s\t\t%s", ++iCount, sKey, "EXPIRES", iClient, sExpires, "USAGE_LEFT", iClient, iUses, "TYPE", iClient, sKeyType, sParams); - } - } - - if(bToFile) - { - CloseHandle(hFile); - } - } - else - { - UTIL_ReplyToCommand(iClient, CmdReplySource, "%t%t", "ERROR", "ERROR_LIST_NO_KEYS"); - } -} diff --git a/addons/sourcemod/scripting/keys/utils.sp b/addons/sourcemod/scripting/keys/utils.sp deleted file mode 100644 index 23e822c..0000000 --- a/addons/sourcemod/scripting/keys/utils.sp +++ /dev/null @@ -1,130 +0,0 @@ - - -UTIL_ReplyToCommand(iClient, ReplySource:CmdReplySource, const String:sFormat[], any:...) -{ - static String:sBuffer[2048]; - SetGlobalTransTarget(iClient); - VFormat(sBuffer, sizeof(sBuffer), sFormat, 4); - - if(iClient) - { - switch(CmdReplySource) - { - case SM_REPLY_TO_CONSOLE: PrintToConsole(iClient, "[KEYS] %s", sBuffer); - case SM_REPLY_TO_CHAT: PrintToChat(iClient, GetEngineVersion() == Engine_CSGO ? " \x04[KEYS] \x01%s":"\x04[KEYS] \x01%s", sBuffer); - } - } - else - { - PrintToServer("[KEYS] %s", sBuffer); - } -} - -UTIL_ValidateKey(String:sKey[], iLength, String:sError[], iErrLen) -{ - if(!sKey[0]) - { - strcopy(sError, iErrLen, "ERROR_KEY_EMPTY"); - return false; - } - - if(iLength < 8) - { - strcopy(sError, iErrLen, "ERROR_KEY_SHORT"); - return false; - } - - if(iLength > 64) - { - strcopy(sError, iErrLen, "ERROR_KEY_LONG"); - return false; - } - - new i = 0; - - while (i < iLength) - { - if((sKey[i] > 0x2F && sKey[i] < 0x3A) || - (sKey[i] > 0x40 && sKey[i] < 0x5B) || - (sKey[i] > 0x60 && sKey[i] < 0x7B) || - sKey[i] == 0x2D) - { - ++i; - continue; - } - - strcopy(sError, iErrLen, "ERROR_KEY_INVALID_CHARACTERS"); - return false; - } - - return true; -} - -UTIL_GenerateKey(String:sKey[]) -{ - sKey[0] = '\0'; - - new i = 0; - - if(g_CVAR_sKeyTemplate[0]) - { - new iLength = strlen(g_CVAR_sKeyTemplate); - while (i < iLength) - { - sKey[i] = UTIL_GetCharTemplate(g_CVAR_sKeyTemplate[i]); - ++i; - } - } - else - { - while (i < g_CVAR_iKeyLength) - { - sKey[i] = UTIL_GetCharTemplate(0x58); - ++i; - } - } - - sKey[i] = '\0'; -} -/* -A - Буква в любом регистре\n\ -B - Цифра 0-9\n\ -X - Цифра 0-9 либо буква в любом регистре\n\ -*/ - -static const g_iNumbers[] = {0x30, 0x39}; -static const g_iLettersUpper[] = {0x41, 0x5A}; -static const g_iLettersLower[] = {0x61, 0x7A}; - -UTIL_GetCharTemplate(iChar) -{ - switch(iChar) - { - // A - буква в любом регистре - case 0x41: return GetRandomInt(1, 20) > 10 ? UTIL_GetRandomInt(g_iLettersUpper[0], g_iLettersUpper[1]):UTIL_GetRandomInt(g_iLettersLower[0], g_iLettersLower[1]); - // B - число 0-9 - case 0x42: return UTIL_GetRandomInt(g_iNumbers[0], g_iNumbers[1]); - // X - число 0-9 либо буква в любом регистре - case 0x58: return GetRandomInt(0, 2) == 1 ? UTIL_GetRandomInt(g_iNumbers[0], g_iNumbers[1]):(GetRandomInt(1, 20) > 10 ? UTIL_GetRandomInt(g_iLettersUpper[0], g_iLettersUpper[1]):UTIL_GetRandomInt(g_iLettersLower[0], g_iLettersLower[1])); - // U - число 0-9 либо буква в верхнем регистре - case 0x55: return GetRandomInt(0, 2) == 1 ? UTIL_GetRandomInt(g_iNumbers[0], g_iNumbers[1]):UTIL_GetRandomInt(g_iLettersUpper[0], g_iLettersUpper[1]); - // L - число 0-9 либо буква в нижнем регистре - case 0x4c: return GetRandomInt(0, 2) == 1 ? UTIL_GetRandomInt(g_iNumbers[0], g_iNumbers[1]):UTIL_GetRandomInt(g_iLettersLower[0], g_iLettersLower[1]); - // Другой символ - default: return iChar; - } - - return iChar; -} - -UTIL_GetRandomInt(iMin, iMax) -{ - new iRandom = GetURandomInt(); - - if (iRandom == 0) - { - ++iRandom; - } - - return RoundToCeil(float(iRandom) / (float(2147483647) / float(iMax - iMin + 1))) + iMin - 1; -} diff --git a/addons/sourcemod/scripting/keys/vars.sp b/addons/sourcemod/scripting/keys/vars.sp deleted file mode 100644 index 3c839a2..0000000 --- a/addons/sourcemod/scripting/keys/vars.sp +++ /dev/null @@ -1,30 +0,0 @@ - -#define UID(%0) GetClientUserId(%0) -#define CID(%0) GetClientOfUserId(%0) -#define SZF(%0) %0, sizeof(%0) - -#define DP_Plugin 0 -#define DP_OnValidateCallback 9 -#define DP_OnUseCallback 18 -#define DP_OnPrintCallback 27 - -new String:g_sLogFile[256]; - -new bool:g_bIsStarted; -new Handle:g_hDatabase, - bool:g_bDBMySQL; - -new bool:g_bIsBlocked[MAXPLAYERS+1], - g_iAttempts[MAXPLAYERS+1]; - -new Handle:g_hKeysTrie; -new Handle:g_hKeysArray; - -new g_iServerID = -1; - -new g_CVAR_iServerID; -new g_CVAR_iKeyLength; -new String:g_CVAR_sKeyTemplate[64]; -new g_CVAR_iAttempts; -new g_CVAR_iBlockTime; - diff --git a/addons/sourcemod/translations/keys_shop_module.phrases.txt b/addons/sourcemod/translations/keys_shop_module.phrases.txt deleted file mode 100644 index a32e437..0000000 --- a/addons/sourcemod/translations/keys_shop_module.phrases.txt +++ /dev/null @@ -1,71 +0,0 @@ -"Phrases" -{ - "ERROR_INVALID_CREDITS" - { - "ru" "Неверное количество кредитов!" - "en" "Wrong number of credits!" - } - - "ERROR_INVALID_CATEGORY" - { - "ru" "Неверная категория!" - "en" "Invalid category!" - } - - "ERROR_INVALID_ITEM" - { - "ru" "Неверный предмет!" - "en" "Wrong subject!" - } - - "CREDITS" - { - "ru" "Кредиты" - "en" "Credits" - } - - "CATEGORY" - { - "ru" "Категория" - "en" "Category" - } - - "ITEM" - { - "ru" "Предмет" - "en" "Subject" - } - - "ALL" - { - "ru" "Все" - "en" "All" - } - - "CHAT_PREFIX" - { - "ru" "[KEYS][Shop] " - "en" "[KEYS][Shop] " - } - - "YOU_RECEIVED_CREDITS" - { - "#format" "{1:d}" - "ru" "Вы получили {1} кредитов!" - "en" "You received {1} credits!" - } - - "YOU_RECEIVED_ITEM_FROM_CATEGORY" - { - "#format" "{1:s},{2:s}" - "ru" "Вы получили {1} из категории {2}!" - "en" "You received {1} from the category {2}!" - } - - "YOU_RECEIVED_ALL_ITEMS_FROM_CATEGORY" - { - "#format" "{1:s}" - "ru" "Вы получили Все предметы из категории {1}!" - "en" "You received All items from the category {1}!" - } -} \ No newline at end of file diff --git a/addons/sourcemod/translations/keys_store_module.phrases.txt b/addons/sourcemod/translations/keys_store_module.phrases.txt deleted file mode 100644 index ae1b43c..0000000 --- a/addons/sourcemod/translations/keys_store_module.phrases.txt +++ /dev/null @@ -1,21 +0,0 @@ -"Phrases" -{ - "ERROR_INVALID_CREDITS" - { - "ru" "Неверное количество кредитов!" - "en" "Wrong number of credits!" - } - - "CREDITS" - { - "ru" "Кредиты" - "en" "Credits" - } - - "YOU_RECEIVED_CREDITS" - { - "#format" "{1:d}" - "ru" "[KEYS][Store] Вы получили {1} кредитов!" - "en" "[KEYS][Store] You received {1} credits!" - } -} \ No newline at end of file diff --git a/addons/sourcemod/translations/keys_wcs_module.phrases.txt b/addons/sourcemod/translations/keys_wcs_module.phrases.txt deleted file mode 100644 index 378d312..0000000 --- a/addons/sourcemod/translations/keys_wcs_module.phrases.txt +++ /dev/null @@ -1,71 +0,0 @@ -"Phrases" -{ - "ERROR_INVALID_RACE" - { - "ru" "Неверная раса!" - "en" "Invalid race!" - } - - "ERROR_INVALID_AMONUT" - { - "ru" "Неверное количество!" - "en" "Invalid amount!" - } - - "ERROR_INVALID_LVL" - { - "ru" "Неверный уровень!" - "en" "Invalid bank lvl!" - } - - "ERROR_HAS_OCCURRED" - { - "ru" "Произошла ошибка!" - "en" "An error has occurred!" - } - - "GOLD" - { - "ru" "Золото" - "en" "Gold" - } - - "PRIVATE_RACE" - { - "ru" "Приватная раса" - "en" "Private race" - } - - "BLVL" - { - "ru" "Уровень банка" - "en" "Bank lvl" - } - - "CHAT_PREFIX" - { - "ru" "[KEYS][WCS] " - "en" "[KEYS][WCS] " - } - - "YOU_RECEIVED_GOLD" - { - "#format" "{1:d}" - "ru" "Вы получили {1} золота!" - "en" "You received {1} gold!" - } - - "YOU_RECEIVED_BLVL" - { - "#format" "{1:d}" - "ru" "Вы получили {1} уровней банка!" - "en" "You received {1} bank levels!" - } - - "YOU_RECEIVED_PRIVATE_RACE" - { - "#format" "{1:s}" - "ru" "Вы получили приватную расу: {1}!" - "en" "You got a private race: {1}!" - } -} \ No newline at end of file