From 2469558ab811e2caca83309a802219a218ae23d9 Mon Sep 17 00:00:00 2001 From: Impact Date: Sun, 27 Aug 2023 22:16:39 +0200 Subject: [PATCH] Update AutoExecConfig include - A percentage sign in a config file could cause an exception --- .../scripting/include/autoexecconfig.inc | 258 +++++++++++------- 1 file changed, 154 insertions(+), 104 deletions(-) diff --git a/gameserver/scripting/include/autoexecconfig.inc b/gameserver/scripting/include/autoexecconfig.inc index 73e07d9..7c51593 100644 --- a/gameserver/scripting/include/autoexecconfig.inc +++ b/gameserver/scripting/include/autoexecconfig.inc @@ -1,3 +1,22 @@ +/** + * AutoExecConfig + * + * Copyright (C) 2013-2019 Impact + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + #if defined _autoexecconfig_included #endinput #endif @@ -6,6 +25,8 @@ #include +#define AUTOEXECCONFIG_VERSION "0.1.6" +#define AUTOEXECCONFIG_URL "https://forums.alliedmods.net/showthread.php?t=204254" // Append #define AUTOEXEC_APPEND_BAD_FILENAME 0 @@ -50,6 +71,8 @@ static char g_sFolderPath[PLATFORM_MAX_PATH]; static bool g_bCreateFile = false; static Handle g_hPluginHandle = null; +static bool g_bCreateDirectory = false; +static int g_bCreateDirectoryMode = FPERM_U_READ|FPERM_U_WRITE|FPERM_U_EXEC|FPERM_G_READ|FPERM_G_EXEC|FPERM_O_READ|FPERM_O_EXEC; // Workaround for now @@ -62,7 +85,7 @@ static int g_iLastAppendResult; /** * Returns the last result from the parser. * - * @return Returns one of the AUTOEXEC_FIND values or -1 if not set. + * @return Returns one of the AUTOEXEC_FIND values or -1 if not set. */ stock int AutoExecConfig_GetFindResult() { @@ -76,7 +99,7 @@ stock int AutoExecConfig_GetFindResult() /** * Returns the last result from the appender. * - * @return Returns one of the AUTOEXEC_APPEND values or -1 if not set. + * @return Returns one of the AUTOEXEC_APPEND values or -1 if not set. */ stock int AutoExecConfig_GetAppendResult() { @@ -85,9 +108,9 @@ stock int AutoExecConfig_GetAppendResult() /** - * Set if the config file should be created if it doesn't exist yet. + * Set if the config file should be created by the autoexecconfig include itself if it doesn't exist. * - * @param create True if config file should be created, false otherwise. + * @param create True if config file should be created, false otherwise. * @noreturn */ stock void AutoExecConfig_SetCreateFile(bool create) @@ -96,10 +119,25 @@ stock void AutoExecConfig_SetCreateFile(bool create) } +/** + * Set if the config file's folder should be created by the autoexecconfig include itself if it doesn't exist. + * Note: Must be used before AutoExecConfig_SetFile as the potential creation of it happens there + * + * @param create True if config file should be created, false otherwise. + * @param mode Folder permission mode, default is u=rwx,g=rx,o=rx. + * @noreturn + */ +stock void AutoExecConfig_SetCreateDirectory(bool create, int mode=FPERM_U_READ|FPERM_U_WRITE|FPERM_U_EXEC|FPERM_G_READ|FPERM_G_EXEC|FPERM_O_READ|FPERM_O_EXEC) +{ + g_bCreateDirectory = create; + g_bCreateDirectoryMode = mode; +} + + /** * Returns if the config file should be created if it doesn't exist. * - * @return Returns true, if the config file should be created or false if it should not. + * @return Returns true, if the config file should be created or false if it should not. */ stock bool AutoExecConfig_GetCreateFile() { @@ -112,7 +150,7 @@ stock bool AutoExecConfig_GetCreateFile() * Set to null to use the calling plugin. * Used to print the correct filename in the top comment when creating the file. * - * @param plugin The plugin to create convars for or null to use the calling plugin. + * @param plugin The plugin to create convars for or null to use the calling plugin. * @noreturn */ stock void AutoExecConfig_SetPlugin(Handle plugin) @@ -122,9 +160,9 @@ stock void AutoExecConfig_SetPlugin(Handle plugin) /** - * Returns the plugin for which the config file is created. + * Returns the plugin's handle for which the config file is created. * - * @return The plugin handle + * @return The plugin handle */ stock Handle AutoExecConfig_GetPlugin() { @@ -134,10 +172,11 @@ stock Handle AutoExecConfig_GetPlugin() /** * Set the global autoconfigfile used by functions of this file. + * Note: does not support subfolders like folder1/folder2 * - * @param file Name of the config file, path and .cfg extension is being added if not given. - * @param folder Folder under cfg/ to use. By default this is "sourcemod." - * @return True if formatter returned success, false otherwise. + * @param file Name of the config file, path and .cfg extension is being added if not given. + * @param folder Folder under cfg/ to use. By default this is "sourcemod." + * @return True if formatter returned success, false otherwise. */ stock bool AutoExecConfig_SetFile(char[] file, char[] folder="sourcemod") { @@ -160,13 +199,13 @@ stock bool AutoExecConfig_SetFile(char[] file, char[] folder="sourcemod") /** * Get the formatted autoconfigfile used by functions of this file. * - * @param buffer String to format. - * @param size Maximum size of buffer - * @return True if filename was set, false otherwise. + * @param buffer String to format. + * @param size Maximum size of buffer + * @return True if filename was set, false otherwise. */ stock bool AutoExecConfig_GetFile(char[] buffer,int size) { - if(strlen(g_sConfigFile) > 0) + if (strlen(g_sConfigFile) > 0) { strcopy(buffer, size, g_sConfigFile); @@ -188,21 +227,21 @@ stock bool AutoExecConfig_GetFile(char[] buffer,int size) * Creates a convar and appends it to the autoconfigfile if not found. * FCVAR_DONTRECORD will be skipped. * - * @param name Name of new convar. - * @param defaultValue String containing the default value of new convar. - * @param description Optional description of the convar. - * @param flags Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details. - * @param hasMin Optional boolean that determines if the convar has a minimum value. - * @param min Minimum floating point value that the convar can have if hasMin is true. - * @param hasMax Optional boolean that determines if the convar has a maximum value. - * @param max Maximum floating point value that the convar can have if hasMax is true. - * @return A handle to the newly created convar. If the convar already exists, a handle to it will still be returned. - * @error Convar name is blank or is the same as an existing console command. + * @param name Name of new convar. + * @param defaultValue String containing the default value of new convar. + * @param description Optional description of the convar. + * @param flags Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details. + * @param hasMin Optional boolean that determines if the convar has a minimum value. + * @param min Minimum floating point value that the convar can have if hasMin is true. + * @param hasMax Optional boolean that determines if the convar has a maximum value. + * @param max Maximum floating point value that the convar can have if hasMax is true. + * @return A handle to the newly created convar. If the convar already exists, a handle to it will still be returned. + * @error Convar name is blank or is the same as an existing console command. */ stock ConVar AutoExecConfig_CreateConVar(const char[] name, const char[] defaultValue, const char[] description="", int flags=0, bool hasMin=false, float min=0.0, bool hasMax=false, float max=0.0) { // If configfile was set and convar has no dontrecord flag - if(!(flags & FCVAR_DONTRECORD) && strlen(g_sConfigFile) > 0) + if (!(flags & FCVAR_DONTRECORD) && strlen(g_sConfigFile) > 0) { // Reset the results g_iLastFindResult = -1; @@ -215,7 +254,7 @@ stock ConVar AutoExecConfig_CreateConVar(const char[] name, const char[] default g_iLastFindResult = AutoExecConfig_FindValue(name, buffer, sizeof(buffer), true); // We only add this convar if it doesn't exist, or the file doesn't exist and it should be auto-generated - if(g_iLastFindResult == AUTOEXEC_FIND_NOT_FOUND || (g_iLastFindResult == AUTOEXEC_FIND_FILE_NOT_FOUND && g_bCreateFile)) + if (g_iLastFindResult == AUTOEXEC_FIND_NOT_FOUND || (g_iLastFindResult == AUTOEXEC_FIND_FILE_NOT_FOUND && g_bCreateFile)) { g_iLastAppendResult = AutoExecConfig_AppendValue(name, defaultValue, description, flags, hasMin, min, hasMax, max); } @@ -230,8 +269,8 @@ stock ConVar AutoExecConfig_CreateConVar(const char[] name, const char[] default /** - * Executes the autoconfigfile, and adds it to the OnConfigsExecuted forward. - * If we didn't created it already we let SourceMod create it. + * Executes the autoconfigfile and adds it to the OnConfigsExecuted forward. + * If we didn't create it ourselves we let SourceMod create it. * * @noreturn */ @@ -246,23 +285,23 @@ stock void AutoExecConfig_ExecuteFile() /** - * Formats a autoconfigfile, prefixes path and adds .cfg extension if missed. + * Formats a autoconfigfile, prefixes path and adds .cfg extension if missing. * - * @param buffer String to format. - * @param size Maximum size of buffer. - * @return Returns one of the AUTOEXEC_FORMAT values.. + * @param buffer String to format. + * @param size Maximum size of buffer. + * @return Returns one of the AUTOEXEC_FORMAT values.. */ stock static int AutoExecConfig_FormatFileName(char[] buffer, int size, char[] folder="sourcemod") { // No config set - if(strlen(g_sConfigFile) < 1) + if (strlen(g_sConfigFile) < 1) { return AUTOEXEC_NO_CONFIG; } // Can't be an cfgfile - if(StrContains(g_sConfigFile, ".cfg") == -1 && strlen(g_sConfigFile) < 4) + if (StrContains(g_sConfigFile, ".cfg") != -1 && strlen(g_sConfigFile) < 4) { return AUTOEXEC_FORMAT_BAD_FILENAME; } @@ -270,9 +309,14 @@ stock static int AutoExecConfig_FormatFileName(char[] buffer, int size, char[] f // Pathprefix char pathprefixbuffer[PLATFORM_MAX_PATH]; - if(strlen(folder) > 0) + if (strlen(folder) > 0) { Format(pathprefixbuffer, sizeof(pathprefixbuffer), "cfg/%s/", folder); + + if (g_bCreateDirectory && !DirExists(pathprefixbuffer)) + { + CreateDirectory(pathprefixbuffer, g_bCreateDirectoryMode); + } } else { @@ -284,7 +328,7 @@ stock static int AutoExecConfig_FormatFileName(char[] buffer, int size, char[] f filebuffer[0] = '\0'; // Add path if file doesn't begin with it - if(StrContains(buffer, pathprefixbuffer) != 0) + if (StrContains(buffer, pathprefixbuffer) != 0) { StrCat(filebuffer, sizeof(filebuffer), pathprefixbuffer); } @@ -293,7 +337,7 @@ stock static int AutoExecConfig_FormatFileName(char[] buffer, int size, char[] f // Add .cfg extension if file doesn't end with it - if(StrContains(filebuffer[strlen(filebuffer) - 4], ".cfg") != 0) + if (StrContains(filebuffer[strlen(filebuffer) - 4], ".cfg") != 0) { StrCat(filebuffer, sizeof(filebuffer), ".cfg"); } @@ -311,20 +355,20 @@ stock static int AutoExecConfig_FormatFileName(char[] buffer, int size, char[] f /** * Appends a convar to the global autoconfigfile * - * @param name Name of new convar. - * @param defaultValue String containing the default value of new convar. - * @param description Optional description of the convar. - * @param flags Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details. - * @param hasMin Optional boolean that determines if the convar has a minimum value. - * @param min Minimum floating point value that the convar can have if hasMin is true. - * @param hasMax Optional boolean that determines if the convar has a maximum value. - * @param max Maximum floating point value that the convar can have if hasMax is true. - * @return Returns one of the AUTOEXEC_APPEND values + * @param name Name of new convar. + * @param defaultValue String containing the default value of new convar. + * @param description Optional description of the convar. + * @param flags Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details. + * @param hasMin Optional boolean that determines if the convar has a minimum value. + * @param min Minimum floating point value that the convar can have if hasMin is true. + * @param hasMax Optional boolean that determines if the convar has a maximum value. + * @param max Maximum floating point value that the convar can have if hasMax is true. + * @return Returns one of the AUTOEXEC_APPEND values */ stock int AutoExecConfig_AppendValue(const char[] name, const char[] defaultValue, const char[] description, int flags, bool hasMin, float min, bool hasMax, float max) { // No config set - if(strlen(g_sConfigFile) < 1) + if (strlen(g_sConfigFile) < 1) { return AUTOEXEC_NO_CONFIG; } @@ -338,26 +382,26 @@ stock int AutoExecConfig_AppendValue(const char[] name, const char[] defaultValu bool bFileExists = FileExists(filebuffer); - if(g_bCreateFile || bFileExists) + if (g_bCreateFile || bFileExists) { // If the file already exists we open it in append mode, otherwise we use a write mode which creates the file File fFile = OpenFile(filebuffer, (bFileExists ? "a" : "w")); char writebuffer[2048]; - if(fFile == null) + if (fFile == null) { return AUTOEXEC_APPEND_BAD_HANDLE; } // We just created the file, so add some header about version and stuff - if(g_bCreateFile && !bFileExists) + if (g_bCreateFile && !bFileExists) { - fFile.WriteLine( "// This file was auto-generated by AutoExecConfig read and append beta"); + fFile.WriteLine( "// This file was auto-generated by AutoExecConfig v%s (%s)", AUTOEXECCONFIG_VERSION, AUTOEXECCONFIG_URL); GetPluginFilename(g_hPluginHandle, writebuffer, sizeof(writebuffer)); Format(writebuffer, sizeof(writebuffer), "// ConVars for plugin \"%s\"", writebuffer); - fFile.WriteLine(writebuffer); + fFile.WriteLine("%s", writebuffer); } // Spacer @@ -366,11 +410,11 @@ stock int AutoExecConfig_AppendValue(const char[] name, const char[] defaultValu // This is used for multiline comments int newlines = GetCharCountInStr('\n', description); - if(newlines == 0) + if (newlines == 0) { // We have no newlines, we can write the description to the file as is Format(writebuffer, sizeof(writebuffer), "// %s", description); - fFile.WriteLine(writebuffer); + fFile.WriteLine("%s", writebuffer); } else { @@ -378,9 +422,9 @@ stock int AutoExecConfig_AppendValue(const char[] name, const char[] defaultValu ExplodeString(description, "\n", newlineBuf, newlines +1, 2048, false); // Each newline gets a commented newline - for(int i; i <= newlines; i++) + for (int i; i <= newlines; i++) { - if(strlen(newlineBuf[i]) > 0) + if (strlen(newlineBuf[i]) > 0) { fFile.WriteLine("// %s", newlineBuf[i]); } @@ -394,36 +438,31 @@ stock int AutoExecConfig_AppendValue(const char[] name, const char[] defaultValu // Default Format(writebuffer, sizeof(writebuffer), "// Default: \"%s\"", defaultValue); - fFile.WriteLine(writebuffer); + fFile.WriteLine("%s", writebuffer); // Minimum - if(hasMin) + if (hasMin) { Format(writebuffer, sizeof(writebuffer), "// Minimum: \"%f\"", min); - fFile.WriteLine(writebuffer); + fFile.WriteLine("%s", writebuffer); } // Maximum - if(hasMax) + if (hasMax) { Format(writebuffer, sizeof(writebuffer), "// Maximum: \"%f\"", max); - fFile.WriteLine(writebuffer); + fFile.WriteLine("%s", writebuffer); } // Write end and defaultvalue Format(writebuffer, sizeof(writebuffer), "%s \"%s\"", name, defaultValue); - fFile.WriteLine(writebuffer); - - - fFile.Close(); - + fFile.WriteLine("%s", writebuffer); - // Clean up the file - //AutoExecConfig_CleanFile(filebuffer, false); + fFile.Close(); return AUTOEXEC_APPEND_SUCCESS; } @@ -437,13 +476,13 @@ stock int AutoExecConfig_AppendValue(const char[] name, const char[] defaultValu /** - * Returns a convars value from the global autoconfigfile + * Returns a convar's value from the global autoconfigfile * - * @param cvar Cvar to search for. - * @param value Buffer to store result into. - * @param size Maximum size of buffer. - * @param caseSensitive Whether or not the search should be case sensitive. - * @return Returns one of the AUTOEXEC_FIND values + * @param cvar Cvar to search for. + * @param value Buffer to store result into. + * @param size Maximum size of buffer. + * @param caseSensitive Whether or not the search should be case sensitive. + * @return Returns one of the AUTOEXEC_FIND values */ stock int AutoExecConfig_FindValue(const char[] cvar, char[] value, int size, bool caseSensitive=false) { @@ -452,7 +491,7 @@ stock int AutoExecConfig_FindValue(const char[] cvar, char[] value, int size, bo // No config set - if(strlen(g_sConfigFile) < 1) + if (strlen(g_sConfigFile) < 1) { return AUTOEXEC_NO_CONFIG; } @@ -468,49 +507,49 @@ stock int AutoExecConfig_FindValue(const char[] cvar, char[] value, int size, bo bool bFileExists = FileExists(filebuffer); // We want to create the config file and it doesn't exist yet. - if(g_bCreateFile && !bFileExists) + if (g_bCreateFile && !bFileExists) { return AUTOEXEC_FIND_FILE_NOT_FOUND; } - if(bFileExists) + if (bFileExists) { File fFile = OpenFile(filebuffer, "r"); int valuestart; int valueend; int cvarend; - // Just an reminder to self, leave the values that high + // Just a reminder to self, leave the values that high char sConvar[64]; char sValue[64]; char readbuffer[2048]; char copybuffer[2048]; - if(fFile == null) + if (fFile == null) { return AUTOEXEC_FIND_BAD_HANDLE; } - while(!fFile.EndOfFile() && fFile.ReadLine(readbuffer, sizeof(readbuffer))) + while (!fFile.EndOfFile() && fFile.ReadLine(readbuffer, sizeof(readbuffer))) { // Is a comment or not valid - if(IsCharSpace(readbuffer[0]) || readbuffer[0] == '/' || !IsCharAlpha(readbuffer[0])) + if (IsCharSpace(readbuffer[0]) || readbuffer[0] == '/' || (!IsCharNumeric(readbuffer[0]) && !IsCharAlpha(readbuffer[0])) ) { continue; } // Has not enough spaces, must have at least 1 - if(GetCharCountInStr(' ', readbuffer) < 1) + if (GetCharCountInStr(' ', readbuffer) < 1) { continue; } // Ignore cvars which aren't quoted - if(GetCharCountInStr('"', readbuffer) != 2) + if (GetCharCountInStr('"', readbuffer) != 2) { continue; } @@ -518,28 +557,28 @@ stock int AutoExecConfig_FindValue(const char[] cvar, char[] value, int size, bo // Get the start of the value - if( (valuestart = StrContains(readbuffer, "\"")) == -1 ) + if ( (valuestart = StrContains(readbuffer, "\"")) == -1 ) { continue; } // Get the end of the value - if( (valueend = StrContains(readbuffer[valuestart+1], "\"")) == -1 ) + if ( (valueend = StrContains(readbuffer[valuestart+1], "\"")) == -1 ) { continue; } // Get the start of the cvar, - if( (cvarend = StrContains(readbuffer, " ")) == -1 || cvarend >= valuestart) + if ( (cvarend = StrContains(readbuffer, " ")) == -1 || cvarend >= valuestart) { continue; } // Skip if cvarendindex is before valuestartindex - if(cvarend >= valuestart) + if (cvarend >= valuestart) { continue; } @@ -563,7 +602,7 @@ stock int AutoExecConfig_FindValue(const char[] cvar, char[] value, int size, bo //PrintToServer("Cvar %s has a value of %s", sConvar, sValue); - if(StrEqual(sConvar, cvar, caseSensitive)) + if (StrEqual(sConvar, cvar, caseSensitive)) { Format(value, size, "%s", sConvar); @@ -588,12 +627,12 @@ stock int AutoExecConfig_FindValue(const char[] cvar, char[] value, int size, bo /** * Cleans the global autoconfigfile from too much spaces * - * @return One of the AUTOEXEC_CLEAN values. + * @return One of the AUTOEXEC_CLEAN values. */ stock int AutoExecConfig_CleanFile() { // No config set - if(strlen(g_sConfigFile) < 1) + if (strlen(g_sConfigFile) < 1) { return AUTOEXEC_NO_CONFIG; } @@ -604,7 +643,7 @@ stock int AutoExecConfig_CleanFile() // Security - if(!FileExists(sfile)) + if (!FileExists(sfile)) { return AUTOEXEC_CLEAN_FILE_NOT_FOUND; } @@ -627,15 +666,15 @@ stock int AutoExecConfig_CleanFile() // Check filehandles - if(fFile1 == null || fFile2 == null) + if (fFile1 == null || fFile2 == null) { - if(fFile1 != null) + if (fFile1 != null) { //PrintToServer("Handle1 invalid"); fFile1.Close(); } - if(fFile2 != null) + if (fFile2 != null) { //PrintToServer("Handle2 invalid"); fFile2.Close(); @@ -646,10 +685,10 @@ stock int AutoExecConfig_CleanFile() - while(!fFile1.EndOfFile() && fFile1.ReadLine(readbuffer, sizeof(readbuffer))) + while (!fFile1.EndOfFile() && fFile1.ReadLine(readbuffer, sizeof(readbuffer))) { // Is space - if(IsCharSpace(readbuffer[0])) + if (IsCharSpace(readbuffer[0])) { count++; } @@ -661,15 +700,15 @@ stock int AutoExecConfig_CleanFile() // Don't write more than 1 space if seperation after informations have been reached - if(count < 2 || !firstreached) + if (count < 2 || !firstreached) { ReplaceString(readbuffer, sizeof(readbuffer), "\n", ""); - fFile2.WriteLine(readbuffer); + fFile2.WriteLine("%s", readbuffer); } // First bigger seperation after informations has been reached - if(count == 2) + if (count == 2) { firstreached = true; } @@ -695,17 +734,17 @@ stock int AutoExecConfig_CleanFile() /** * Returns how many times the given char occures in the given string. * - * @param str String to search for in. - * @return Occurences of the given char found in string. + * @param str String to search for in. + * @return Occurences of the given char found in string. */ stock static int GetCharCountInStr(int character, const char[] str) { int len = strlen(str); int count; - for(int i; i < len; i++) + for (int i; i < len; i++) { - if(str[i] == character) + if (str[i] == character) { count++; } @@ -713,3 +752,14 @@ stock static int GetCharCountInStr(int character, const char[] str) return count; } + + + + + + +#pragma deprecated +stock bool AutoExecConfig_CacheConvars() +{ + return false; +}