// The C Plus Plus headers. #include #include #include #include #include #include // The other further headers. #include "Header.h" #include "amxxmodule.h" #include "sqlite3.h" // The definitions. #define MAXIMUM_CHARACTERS_FOR_STRING 4096U #define MAXIMUM_CHARACTERS_FOR_COLUMN 128U #define MAXIMUM_ROWS_TO_SELECT 2048U #define MAXIMUM_COLUMNS_TO_HAVE 64U // The Database_Row class. Each row will contain 64 columns as long as 128 maximum characters. class Database_Row { public: char Column[MAXIMUM_COLUMNS_TO_HAVE][MAXIMUM_CHARACTERS_FOR_COLUMN]; }; // The data used into the extension. Database_Row g_Row[MAXIMUM_ROWS_TO_SELECT]; sqlite3 * g_Handle = NULL; char g_String[MAXIMUM_CHARACTERS_FOR_STRING]; int g_Rows = 0U; int g_Iterator = 0U; int g_Length = 0U; // The SQLite handlers. int SQLite_SelectQueryHandler(void *, int Count, char ** Data, char **) { if (g_Rows < MAXIMUM_ROWS_TO_SELECT) { for (g_Iterator = 0; g_Iterator < Count && g_Iterator < MAXIMUM_COLUMNS_TO_HAVE; g_Iterator++) { _snprintf(g_Row[g_Rows].Column[g_Iterator], MAXIMUM_CHARACTERS_FOR_COLUMN, "%s", \ Data[g_Iterator] ? Data[g_Iterator] : "NULL"); } } // Let this one to increment everytime. It will be usefull for getting the rows count from any table. g_Rows++; return 0U; } int SQLite_UpdateQueryHandler(void *, int, char **, char **) { // Do nothing. return 0U; } // The AMX Mod X functions. static cell AMX_NATIVE_CALL Query(AMX * Handle, cell * Parameters) { g_Rows = 0U; sqlite3_exec(g_Handle, MF_GetAmxString(Handle, Parameters[1U], 0U, 0U), Parameters[2U] ? \ SQLite_SelectQueryHandler : SQLite_UpdateQueryHandler, NULL, NULL); return g_Rows; } static cell AMX_NATIVE_CALL Get(AMX * Handle, cell * Parameters) { // If the coder will fail, this won't log any error. Will just set the buffer as "NULL" and will return zero. if (Parameters[1U] >= 0U && Parameters[1U] < MAXIMUM_ROWS_TO_SELECT && Parameters[2U] >= 0U && \ Parameters[2U] < MAXIMUM_COLUMNS_TO_HAVE) { MF_SetAmxString(Handle, Parameters[3U], g_Row[Parameters[1U]].Column[Parameters[2U]], Parameters[4U]); return (cell)atoi(g_Row[Parameters[1U]].Column[Parameters[2U]]); } MF_SetAmxString(Handle, Parameters[3U], "NULL", Parameters[4U]); return 0U; } static cell AMX_NATIVE_CALL Safe(AMX * Handle, cell * Parameters) { // Run into an error whether coder wants to replace a bad character with another bad character. if (Parameters[2] == '\'' || Parameters[2] == '"' || Parameters[2] == '\\' || Parameters[2] == '`') { MF_LogError(Handle, AMX_ERR_NATIVE, \ "Unable to replace a bad character with another bad character. Bad characters are \\, ', \" and `."); return 0U; } g_Length = _snprintf(g_String, MAXIMUM_CHARACTERS_FOR_STRING, "%s", MF_GetAmxString(Handle, Parameters[1U], 0U, 0U)); // Check for each character. for (g_Iterator = 0; g_Iterator < g_Length; g_Iterator++) { if (g_String[g_Iterator] == '\'' || g_String[g_Iterator] == '"' || g_String[g_Iterator] == '\\' \ || g_String[g_Iterator] == '`') { // Replace bad character with the given one. g_String[g_Iterator] = Parameters[2U]; } } MF_SetAmxString(Handle, Parameters[1U], g_String, g_Length); return 1U; } // Functions bundle. const AMX_NATIVE_INFO g_Functions[] = { { "Database_Query", Query }, { "Database_Get", Get }, { "Database_Safe", Safe }, { NULL, NULL } }; // AMX Mod X forwards. void OnAmxxAttach(void) { MF_AddNatives(g_Functions); sqlite3_open("Database.SQ3", &g_Handle); } void OnAmxxDetach(void) { sqlite3_close(g_Handle); }