diff options
| author | navewindre <nw@moneybot.cc> | 2023-11-13 14:28:08 +0100 |
|---|---|---|
| committer | navewindre <nw@moneybot.cc> | 2023-11-13 14:28:08 +0100 |
| commit | da518fdc0f32839730ccdee8098b59c6f842d93f (patch) | |
| tree | d6f856a6148c0b4d5819f88f068b7287b8044513 /sourcemod-1.5-dev/scripting/include/smlib/files.inc | |
| parent | bc678b10830cdaef64bcc592ca2524ebe0fcdc45 (diff) | |
ya
Diffstat (limited to 'sourcemod-1.5-dev/scripting/include/smlib/files.inc')
| -rw-r--r-- | sourcemod-1.5-dev/scripting/include/smlib/files.inc | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/files.inc b/sourcemod-1.5-dev/scripting/include/smlib/files.inc new file mode 100644 index 0000000..3fda876 --- /dev/null +++ b/sourcemod-1.5-dev/scripting/include/smlib/files.inc @@ -0,0 +1,458 @@ +#if defined _smlib_files_included + #endinput +#endif +#define _smlib_files_included + +#include <sourcemod> +#include <sdktools> +#include <smlib/arrays> + +/** + * Gets the Base name of a path. + * Examples: + * blub.txt -> "blub.txt" + * /sourcemod/extensions/example.ext.so -> "example.ext.so" + * + * @param path File path + * @param buffer String buffer array + * @param size Size of string buffer + * @noreturn + */ +stock bool:File_GetBaseName(const String:path[], String:buffer[], size) +{ + if (path[0] == '\0') { + buffer[0] = '\0'; + return; + } + + new pos_start = FindCharInString(path, '/', true); + + if (pos_start == -1) { + pos_start = FindCharInString(path, '\\', true); + } + + pos_start++; + + strcopy(buffer, size, path[pos_start]); +} + +/** + * Gets the Directory of a path (without the file name). + * Does not work with "." as the path. + * Examples: + * blub.txt -> "blub.txt" + * /sourcemod/extensions/example.ext.so -> "example.ext.so" + * + * @param path File path + * @param buffer String buffer array + * @param size Size of string buffer + * @noreturn + */ +stock bool:File_GetDirName(const String:path[], String:buffer[], size) +{ + if (path[0] == '\0') { + buffer[0] = '\0'; + return; + } + + new pos_start = FindCharInString(path, '/', true); + + if (pos_start == -1) { + pos_start = FindCharInString(path, '\\', true); + + if (pos_start == -1) { + buffer[0] = '\0'; + return; + } + } + + strcopy(buffer, size, path); + buffer[pos_start] = '\0'; +} + +/** + * Gets the File name of a path. + * blub.txt -> "blub" + * /sourcemod/extensions/example.ext.so -> "example.ext" + * + * @param path File path + * @param buffer String buffer array + * @param size Size of string buffer + * @noreturn + */ +stock bool:File_GetFileName(const String:path[], String:buffer[], size) +{ + if (path[0] == '\0') { + buffer[0] = '\0'; + return; + } + + File_GetBaseName(path, buffer, size); + + new pos_ext = FindCharInString(buffer, '.', true); + + if (pos_ext != -1) { + buffer[pos_ext] = '\0'; + } +} + +/** + * Gets the Extension of a file. + * Examples: + * blub.inc.txt -> "txt" + * /sourcemod/extensions/example.ext.so -> "so" + * + * @param path Path String + * @param buffer String buffer array + * @param size Max length of string buffer + * @noreturn + */ +stock File_GetExtension(const String:path[], String:buffer[], size) +{ + new extpos = FindCharInString(path, '.', true); + + if (extpos == -1) { + buffer[0] = '\0'; + return; + } + + strcopy(buffer, size, path[++extpos]); +} + +/** + * Adds a path to the downloadables network string table. + * This can be a file or directory and also works recursed. + * You can optionally specify file extensions that should be ignored. + * Bz2 and ztmp are automatically ignored. + * It only adds files that actually exist. + * You can also specify a wildcard * after the ., very useful for models. + * This forces a client to download the file if they do not already have it. + * + * @param path Path String + * @param recursive Whether to do recursion or not. + * @param ignoreExts Optional: 2 dimensional String array.You can define it like this: new String:ignore[][] = { ".ext1", ".ext2" }; + * @param size This should be set to the number of file extensions in the ignoreExts array (sizeof(ignore) for the example above) + * @noreturn + */ + +// Damn you SourcePawn :( I didn't want to +new String:_smlib_empty_twodimstring_array[][] = { { '\0' } }; +stock File_AddToDownloadsTable(const String:path[], bool:recursive=true, const String:ignoreExts[][]=_smlib_empty_twodimstring_array, size=0) +{ + if (path[0] == '\0') { + return; + } + + if (FileExists(path)) { + + new String:fileExtension[5]; + File_GetExtension(path, fileExtension, sizeof(fileExtension)); + + if (StrEqual(fileExtension, "bz2", false) || StrEqual(fileExtension, "ztmp", false)) { + return; + } + + if (Array_FindString(ignoreExts, size, fileExtension) != -1) { + return; + } + + decl String:path_new[PLATFORM_MAX_PATH]; + strcopy(path_new, sizeof(path_new), path); + ReplaceString(path_new, sizeof(path_new), "//", "/"); + + AddFileToDownloadsTable(path_new); + } + else if (recursive && DirExists(path)) { + + decl String:dirEntry[PLATFORM_MAX_PATH]; + new Handle:__dir = OpenDirectory(path); + + while (ReadDirEntry(__dir, dirEntry, sizeof(dirEntry))) { + + if (StrEqual(dirEntry, ".") || StrEqual(dirEntry, "..")) { + continue; + } + + Format(dirEntry, sizeof(dirEntry), "%s/%s", path, dirEntry); + File_AddToDownloadsTable(dirEntry, recursive, ignoreExts, size); + } + + CloseHandle(__dir); + } + else if (FindCharInString(path, '*', true)) { + + new String:fileExtension[4]; + File_GetExtension(path, fileExtension, sizeof(fileExtension)); + + if (StrEqual(fileExtension, "*")) { + + decl + String:dirName[PLATFORM_MAX_PATH], + String:fileName[PLATFORM_MAX_PATH], + String:dirEntry[PLATFORM_MAX_PATH]; + + File_GetDirName(path, dirName, sizeof(dirName)); + File_GetFileName(path, fileName, sizeof(fileName)); + StrCat(fileName, sizeof(fileName), "."); + + new Handle:__dir = OpenDirectory(dirName); + while (ReadDirEntry(__dir, dirEntry, sizeof(dirEntry))) { + + if (StrEqual(dirEntry, ".") || StrEqual(dirEntry, "..")) { + continue; + } + + if (strncmp(dirEntry, fileName, strlen(fileName)) == 0) { + Format(dirEntry, sizeof(dirEntry), "%s/%s", dirName, dirEntry); + File_AddToDownloadsTable(dirEntry, recursive, ignoreExts, size); + } + } + + CloseHandle(__dir); + } + } + + return; +} + + +/* + * Adds all files/paths in the given text file to the download table. + * Recursive mode enabled, see File_AddToDownloadsTable() + * Comments are allowed ! Supported comment types are ; // # + * + * @param path Path to the .txt file. + * @noreturn + */ +stock File_ReadDownloadList(const String:path[]) +{ + new Handle:file = OpenFile(path, "r"); + + if (file == INVALID_HANDLE) { + return; + } + + new String:buffer[PLATFORM_MAX_PATH]; + while (!IsEndOfFile(file)) { + ReadFileLine(file, buffer, sizeof(buffer)); + + new pos; + pos = StrContains(buffer, "//"); + if (pos != -1) { + buffer[pos] = '\0'; + } + + pos = StrContains(buffer, "#"); + if (pos != -1) { + buffer[pos] = '\0'; + } + + pos = StrContains(buffer, ";"); + if (pos != -1) { + buffer[pos] = '\0'; + } + + TrimString(buffer); + + if (buffer[0] == '\0') { + continue; + } + + File_AddToDownloadsTable(buffer); + } + + CloseHandle(file); +} + +/* + * Attempts to load a translation file and optionally unloads the plugin if the file + * doesn't exist (also prints an error message). + * + * @param file Filename of the translations file (eg. <pluginname>.phrases). + * @param setFailState If true, it sets the failstate if the translations file doesn't exist + * @return True on success, false otherwise (only if setFailState is set to false) + */ +stock File_LoadTranslations(const String:file[], setFailState=true) +{ + decl String:path[PLATFORM_MAX_PATH]; + + BuildPath(Path_SM, path, sizeof(path), "translations/%s", file); + + if (FileExists(path)) { + LoadTranslations(file); + return true; + } + + Format(path,sizeof(path), "%s.txt", path); + + if (!FileExists(path)) { + + if (setFailState) { + SetFailState("Unable to locate translation file (%s).", path); + } + + return false; + } + + LoadTranslations(file); + + return true; +} + +/* + * Reads the contents of a given file into a string buffer in binary mode. + * + * @param path Path to the file + * @param buffer String buffer + * @param size If -1, reads until a null terminator is encountered in the file. Otherwise, read_count bytes are read into the buffer provided. In this case the buffer is not explicitly null terminated, and the buffer will contain any null terminators read from the file. + * @return Number of characters written to the buffer, or -1 if an error was encountered. + */ +stock File_ToString(const String:path[], String:buffer[], size) +{ + new Handle:file = OpenFile(path, "rb"); + + if (file == INVALID_HANDLE) { + buffer[0] = '\0'; + return -1; + } + + new num_bytes_written = ReadFileString(file, buffer, size); + CloseHandle(file); + + return num_bytes_written; +} + +/* + * Writes a string into a file in binary mode. + * + * @param file Path to the file + * @param str String to write + * @return True on success, false otherwise + */ +stock bool:File_StringToFile(const String:path[], String:str[]) +{ + new Handle:file = OpenFile(path, "wb"); + + if (file == INVALID_HANDLE) { + return false; + } + + new bool:success = WriteFileString(file, str, false); + CloseHandle(file); + + return success; +} + +/* + * Copies file source to destination + * Based on code of javalia: + * http://forums.alliedmods.net/showthread.php?t=159895 + * + * @param source Input file + * @param destination Output file + */ +stock bool:File_Copy(const String:source[], const String:destination[]) +{ + new Handle:file_source = OpenFile(source, "rb"); + + if (file_source == INVALID_HANDLE) { + return false; + } + + new Handle:file_destination = OpenFile(destination, "wb"); + + if (file_destination == INVALID_HANDLE) { + CloseHandle(file_source); + return false; + } + + new buffer[32]; + new cache; + + while (!IsEndOfFile(file_source)) { + cache = ReadFile(file_source, buffer, 32, 1); + WriteFile(file_destination, buffer, cache, 1); + } + + CloseHandle(file_source); + CloseHandle(file_destination); + + return true; +} + +/* + * Recursively copies (the content) of a directory or file specified + * by "path" to "destination". + * Note that because of Sourcemod API limitations this currently does not + * takeover the file permissions (it leaves them default). + * Links will be resolved. + * + * @param path Source path + * @param destination Destination directory (This can only be a directory) + * @param stop_on_error Optional: Set to true to stop on error (ie can't read a file) + * @param dirMode Optional: File mode for directories that will be created (Default = 0755), don't forget to convert FROM octal + */ +stock bool:File_CopyRecursive(const String:path[], const String:destination[], bool:stop_on_error=false, dirMode=493) +{ + if (FileExists(path)) { + return File_Copy(path, destination); + } + else if (DirExists(path)) { + return Sub_File_CopyRecursive(path, destination, stop_on_error, FileType_Directory, dirMode); + } + else { + return false; + } +} + +static stock bool:Sub_File_CopyRecursive(const String:path[], const String:destination[], bool:stop_on_error=false, FileType:fileType, dirMode) +{ + if (fileType == FileType_File) { + return File_Copy(path, destination); + } + else if (fileType == FileType_Directory) { + + if (!CreateDirectory(destination, dirMode) && stop_on_error) { + return false; + } + + new Handle:directory = OpenDirectory(path); + + if (directory == INVALID_HANDLE) { + return false; + } + + decl + String:source_buffer[PLATFORM_MAX_PATH], + String:destination_buffer[PLATFORM_MAX_PATH]; + new FileType:type; + + while (ReadDirEntry(directory, source_buffer, sizeof(source_buffer), type)) { + + if (StrEqual(source_buffer, "..") || StrEqual(source_buffer, ".")) { + continue; + } + + Format(destination_buffer, sizeof(destination_buffer), "%s/%s", destination, source_buffer); + Format(source_buffer, sizeof(source_buffer), "%s/%s", path, source_buffer); + + if (type == FileType_File) { + File_Copy(source_buffer, destination_buffer); + } + else if (type == FileType_Directory) { + + if (!File_CopyRecursive(source_buffer, destination_buffer, stop_on_error, dirMode) && stop_on_error) { + CloseHandle(directory); + return false; + } + } + } + + CloseHandle(directory); + } + else if (fileType == FileType_Unknown) { + return false; + } + + return true; +} |
