mirror of
https://github.com/Team-Resurgent/UIXLiteFTP.git
synced 2026-08-15 11:18:21 -07:00
523 lines
14 KiB
C++
523 lines
14 KiB
C++
#include "IniUtility.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "pointerVector.h"
|
|
|
|
namespace {
|
|
char* trim(char* str)
|
|
{
|
|
if (str == NULL) return NULL;
|
|
|
|
// Trim leading spaces
|
|
char* start = str;
|
|
while (*start == ' ' || *start == '\t' || *start == '\r' || *start == '\n') start++;
|
|
|
|
// Trim trailing spaces
|
|
char* end = start + strlen(start) - 1;
|
|
while (end > start && (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n')) end--;
|
|
*(end + 1) = '\0';
|
|
|
|
return start;
|
|
}
|
|
|
|
bool isSection(char* line, char* sectionName)
|
|
{
|
|
if (line && line[0] == '[')
|
|
{
|
|
char* end = strchr(line, ']');
|
|
if (end)
|
|
{
|
|
strncpy(sectionName, line + 1, end - line - 1);
|
|
sectionName[end - line - 1] = '\0';
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool isKeyValuePair(char* line, char* key, char* value, bool& hasSpaces)
|
|
{
|
|
char* equalPos = strchr(line, '=');
|
|
if (equalPos)
|
|
{
|
|
strncpy(key, line, equalPos - line);
|
|
key[equalPos - line] = '\0';
|
|
strcpy(value, equalPos + 1);
|
|
|
|
// Check if spaces are around '='
|
|
hasSpaces = (strstr(line, " = ") != NULL);
|
|
trim(key);
|
|
trim(value);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
char* IniUtility::GetValue(const char* filename, const char* section, const char* key)
|
|
{
|
|
FILE* file = fopen(filename, "r");
|
|
if (!file) return strdup("");
|
|
|
|
char line[MAX_LINE_SIZE], currentSection[256];
|
|
char keyStr[256];
|
|
strcpy(keyStr, key);
|
|
bool inGlobalSection = isNullOrEmpty(section);
|
|
|
|
while (fgets(line, sizeof(line), file))
|
|
{
|
|
char* trimmedLine = trim(line);
|
|
if (*trimmedLine == '\0' || *trimmedLine == ';') continue;
|
|
|
|
if (isSection(trimmedLine, currentSection))
|
|
{
|
|
inGlobalSection = false;
|
|
if (strcmp(currentSection, section) == 0)
|
|
{
|
|
inGlobalSection = true;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
char foundKey[256], foundValue[MAX_VALUE_SIZE];
|
|
bool hasSpaces;
|
|
if (isKeyValuePair(trimmedLine, foundKey, foundValue, hasSpaces))
|
|
{
|
|
if ((inGlobalSection || strcmp(currentSection, section) == 0) && strcmp(foundKey, key) == 0)
|
|
{
|
|
char* result = strdup(foundValue);
|
|
fclose(file);
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
fclose(file);
|
|
return strdup("");
|
|
}
|
|
|
|
bool IniUtility::SetValue(const char* filename, const char* section, const char* key, const char* value)
|
|
{
|
|
FILE* file = fopen(filename, "rb");
|
|
bool fileExists = (file != NULL);
|
|
char* fileContent = NULL;
|
|
long fileSize = 0;
|
|
|
|
if (fileExists)
|
|
{
|
|
// Get file size
|
|
fseek(file, 0, SEEK_END);
|
|
fileSize = ftell(file);
|
|
fseek(file, 0, SEEK_SET);
|
|
|
|
fileContent = new char[fileSize + 1]; // +1 for null terminator
|
|
if (!fileContent)
|
|
{
|
|
fclose(file);
|
|
return false;
|
|
}
|
|
|
|
fread(fileContent, 1, fileSize, file);
|
|
fileContent[fileSize] = '\0';
|
|
fclose(file);
|
|
}
|
|
|
|
// Prepare buffer for the new content
|
|
char* newContent = new char[fileSize + 1280]; // Allocate some extra space for new content
|
|
if (!newContent)
|
|
{
|
|
if (fileContent) delete[] fileContent;
|
|
return false;
|
|
}
|
|
newContent[0] = '\0'; // Start with an empty string
|
|
|
|
char line[MAX_LINE_SIZE], currentSection[256], previousSection[256] = "";
|
|
char keyStr[256], valueStr[MAX_VALUE_SIZE];
|
|
strcpy(keyStr, key);
|
|
strcpy(valueStr, value);
|
|
bool keyUpdated = false;
|
|
bool inGlobalSection = true;
|
|
bool firstFormatDetected = false;
|
|
bool useSpaces = false; // Determines if spaces should be used around '='
|
|
if (fileExists && fileContent)
|
|
{
|
|
char* currentLine = strtok(fileContent, "\r\n");
|
|
|
|
while (currentLine)
|
|
{
|
|
strncpy(line, currentLine, sizeof(line) - 1);
|
|
line[sizeof(line) - 1] = '\0'; // Ensure null-termination
|
|
char* trimmedLine = trim(line);
|
|
|
|
if (*trimmedLine == '\0' || *trimmedLine == ';')
|
|
{
|
|
strcat(newContent, line);
|
|
strcat(newContent, "\r\n");
|
|
currentLine = strtok(NULL, "\r\n");
|
|
continue;
|
|
}
|
|
|
|
char foundKey[256], foundValue[MAX_VALUE_SIZE];
|
|
bool lineHasSpaces;
|
|
if (isSection(trimmedLine, currentSection))
|
|
{
|
|
if (!keyUpdated && strcmp(previousSection, section) == 0)
|
|
{
|
|
strcat(newContent, keyStr);
|
|
strcat(newContent, useSpaces ? " = " : "=");
|
|
strcat(newContent, valueStr);
|
|
strcat(newContent, "\r\n");
|
|
keyUpdated = true;
|
|
}
|
|
strcpy(previousSection, currentSection);
|
|
strcat(newContent, line);
|
|
strcat(newContent, "\r\n");
|
|
inGlobalSection = false;
|
|
currentLine = strtok(NULL, "\r\n");
|
|
continue;
|
|
}
|
|
|
|
if (isKeyValuePair(trimmedLine, foundKey, foundValue, lineHasSpaces))
|
|
{
|
|
if (!firstFormatDetected)
|
|
{
|
|
useSpaces = lineHasSpaces;
|
|
firstFormatDetected = true;
|
|
}
|
|
|
|
if ((inGlobalSection || strcmp(currentSection, section) == 0) && strcmp(foundKey, keyStr) == 0)
|
|
{
|
|
strcat(newContent, keyStr);
|
|
strcat(newContent, useSpaces ? " = " : "=");
|
|
strcat(newContent, valueStr);
|
|
strcat(newContent, "\r\n");
|
|
keyUpdated = true;
|
|
currentLine = strtok(NULL, "\r\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
strcat(newContent, line);
|
|
strcat(newContent, "\r\n");
|
|
currentLine = strtok(NULL, "\r\n");
|
|
}
|
|
}
|
|
if (!keyUpdated)
|
|
{
|
|
// Add the new section and key-value if it wasn't found and updated
|
|
if ((!inGlobalSection && strcmp(currentSection, section) != 0)
|
|
|| (inGlobalSection && !isNullOrEmpty(section)))
|
|
{
|
|
strcat(newContent, "[");
|
|
strcat(newContent, section);
|
|
strcat(newContent, "]\r\n");
|
|
}
|
|
strcat(newContent, keyStr);
|
|
strcat(newContent, useSpaces ? " = " : "=");
|
|
strcat(newContent, valueStr);
|
|
strcat(newContent, "\r\n");
|
|
}
|
|
|
|
// Open the file again for writing
|
|
file = fopen(filename, "wb");
|
|
if (!file)
|
|
{
|
|
if (fileContent) delete[] fileContent;
|
|
delete[] newContent;
|
|
return false;
|
|
}
|
|
|
|
// Write the updated content to the file
|
|
fwrite(newContent, sizeof(char), strlen(newContent), file);
|
|
|
|
// Clean up
|
|
fclose(file);
|
|
if (fileContent) delete[] fileContent;
|
|
delete[] newContent;
|
|
|
|
return true;
|
|
}
|
|
|
|
pointerVector<char*>* IniUtility::GetSectionNames(const char* filename)
|
|
{
|
|
FILE* file = fopen(filename, "r");
|
|
if (!file)
|
|
{
|
|
return new pointerVector<char*>(false);
|
|
}
|
|
|
|
char line[MAX_LINE_SIZE];
|
|
pointerVector<char*>* sections = new pointerVector<char*>(false);
|
|
|
|
while (fgets(line, sizeof(line), file))
|
|
{
|
|
char sectionName[256];
|
|
if (isSection(trim(line), sectionName))
|
|
{
|
|
char* section = strdup(sectionName);
|
|
sections->add(section);
|
|
}
|
|
}
|
|
|
|
fclose(file);
|
|
return sections;
|
|
}
|
|
|
|
pointerVector<char*>* IniUtility::GetSectionKeys(const char* filename, const char* section)
|
|
{
|
|
FILE* file = fopen(filename, "r");
|
|
if (!file)
|
|
{
|
|
return new pointerVector<char*>(false);
|
|
}
|
|
|
|
char line[MAX_LINE_SIZE], currentSection[256];
|
|
pointerVector<char*>* keys = new pointerVector<char*>(false);
|
|
bool inGlobalSection = isNullOrEmpty(section);
|
|
|
|
while (fgets(line, sizeof(line), file))
|
|
{
|
|
char* trimmedLine = trim(line);
|
|
if (*trimmedLine == '\0' || *trimmedLine == ';') continue;
|
|
|
|
if (isSection(trimmedLine, currentSection))
|
|
{
|
|
inGlobalSection = false;
|
|
if (strcmp(currentSection, section) == 0)
|
|
{
|
|
inGlobalSection = true;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (inGlobalSection || strcmp(currentSection, section) == 0)
|
|
{
|
|
char key[256], value[MAX_VALUE_SIZE];
|
|
bool hasSpaces;
|
|
if (isKeyValuePair(trimmedLine, key, value, hasSpaces))
|
|
{
|
|
char* keyCStr = strdup(key);
|
|
keys->add(keyCStr);
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(file);
|
|
return keys;
|
|
}
|
|
|
|
bool IniUtility::DeleteKey(const char* filename, const char* section, const char* key)
|
|
{
|
|
FILE* file = fopen(filename, "rb");
|
|
if (!file)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Get file size
|
|
fseek(file, 0, SEEK_END);
|
|
long fileSize = ftell(file);
|
|
fseek(file, 0, SEEK_SET);
|
|
|
|
// Allocate memory to read the entire file
|
|
char* fileContent = new char[fileSize + 1];
|
|
if (!fileContent)
|
|
{
|
|
fclose(file);
|
|
return false;
|
|
}
|
|
|
|
// Read the entire file into memory
|
|
fread(fileContent, 1, fileSize, file);
|
|
fileContent[fileSize] = '\0'; // Null terminate the string
|
|
fclose(file);
|
|
|
|
// Prepare buffer for the new content
|
|
char* newContent = new char[fileSize + 1];
|
|
if (!newContent)
|
|
{
|
|
delete[] fileContent;
|
|
return false;
|
|
}
|
|
newContent[0] = '\0'; // Start with an empty string
|
|
|
|
char line[MAX_LINE_SIZE], currentSection[256];
|
|
bool keyDeleted = false;
|
|
bool inGlobalSection = isNullOrEmpty(section);
|
|
|
|
char* currentLine = strtok(fileContent, "\r\n");
|
|
while (currentLine)
|
|
{
|
|
strncpy(line, currentLine, sizeof(line) - 1);
|
|
line[sizeof(line) - 1] = '\0'; // Ensure null-termination
|
|
char* trimmedLine = trim(line);
|
|
|
|
if (*trimmedLine == '\0' || *trimmedLine == ';')
|
|
{
|
|
strcat(newContent, line);
|
|
strcat(newContent, "\r\n");
|
|
currentLine = strtok(NULL, "\r\n");
|
|
continue;
|
|
}
|
|
|
|
char foundKey[256], foundValue[MAX_VALUE_SIZE];
|
|
bool hasSpaces;
|
|
if (isSection(trimmedLine, currentSection))
|
|
{
|
|
strcat(newContent, line);
|
|
strcat(newContent, "\r\n");
|
|
inGlobalSection = false;
|
|
currentLine = strtok(NULL, "\r\n");
|
|
continue;
|
|
}
|
|
|
|
if ((inGlobalSection || strcmp(currentSection, section) == 0) && isKeyValuePair(trimmedLine, foundKey, foundValue, hasSpaces))
|
|
{
|
|
if (strcmp(foundKey, key) == 0)
|
|
{
|
|
keyDeleted = true;
|
|
currentLine = strtok(NULL, "\r\n");
|
|
continue; // Skip writing this line to delete the key
|
|
}
|
|
}
|
|
|
|
strcat(newContent, line);
|
|
strcat(newContent, "\r\n");
|
|
currentLine = strtok(NULL, "\r\n");
|
|
}
|
|
|
|
if (!keyDeleted)
|
|
{
|
|
delete[] fileContent;
|
|
delete[] newContent;
|
|
return false;
|
|
}
|
|
|
|
// Open the file again for writing
|
|
file = fopen(filename, "wb");
|
|
if (!file)
|
|
{
|
|
delete[] fileContent;
|
|
delete[] newContent;
|
|
return false;
|
|
}
|
|
|
|
// Write the updated content to the file
|
|
fwrite(newContent, sizeof(char), strlen(newContent), file);
|
|
|
|
// Clean up
|
|
fclose(file);
|
|
delete[] fileContent;
|
|
delete[] newContent;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool IniUtility::DeleteSection(const char* filename, const char* section)
|
|
{
|
|
FILE* file = fopen(filename, "rb");
|
|
if (!file)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Get file size
|
|
fseek(file, 0, SEEK_END);
|
|
long fileSize = ftell(file);
|
|
fseek(file, 0, SEEK_SET);
|
|
|
|
// Allocate memory to read the entire file
|
|
char* fileContent = new char[fileSize + 1];
|
|
if (!fileContent)
|
|
{
|
|
fclose(file);
|
|
return false;
|
|
}
|
|
|
|
// Read the entire file into memory
|
|
fread(fileContent, 1, fileSize, file);
|
|
fileContent[fileSize] = '\0'; // Null terminate the string
|
|
fclose(file);
|
|
|
|
// Prepare buffer for the new content
|
|
char* newContent = new char[fileSize + 1];
|
|
if (!newContent)
|
|
{
|
|
delete[] fileContent;
|
|
return false;
|
|
}
|
|
newContent[0] = '\0'; // Start with an empty string
|
|
|
|
char line[MAX_LINE_SIZE];
|
|
bool sectionDeleted = false;
|
|
bool inTargetSection = false;
|
|
bool deleteGlobal = isNullOrEmpty(section);
|
|
|
|
char* currentLine = strtok(fileContent, "\r\n");
|
|
while (currentLine)
|
|
{
|
|
strncpy(line, currentLine, sizeof(line) - 1);
|
|
line[sizeof(line) - 1] = '\0'; // Ensure null-termination
|
|
char* trimmedLine = trim(line);
|
|
|
|
if (*trimmedLine == '\0' || *trimmedLine == ';')
|
|
{
|
|
if (!inTargetSection)
|
|
{
|
|
strcat(newContent, line);
|
|
strcat(newContent, "\r\n");
|
|
}
|
|
currentLine = strtok(NULL, "\r\n");
|
|
continue;
|
|
}
|
|
|
|
char sectionName[256];
|
|
if (isSection(trimmedLine, sectionName))
|
|
{
|
|
if (inTargetSection)
|
|
{
|
|
inTargetSection = false;
|
|
sectionDeleted = true; // Mark section deletion complete
|
|
}
|
|
if (!deleteGlobal && strcmp(sectionName, section) == 0)
|
|
{
|
|
inTargetSection = true;
|
|
sectionDeleted = true;
|
|
currentLine = strtok(NULL, "\r\n");
|
|
continue; // Skip writing this section
|
|
}
|
|
}
|
|
|
|
if (!inTargetSection)
|
|
{
|
|
strcat(newContent, line);
|
|
strcat(newContent, "\r\n");
|
|
}
|
|
currentLine = strtok(NULL, "\r\n");
|
|
}
|
|
|
|
if (!sectionDeleted && !deleteGlobal)
|
|
{
|
|
delete[] fileContent;
|
|
delete[] newContent;
|
|
return false;
|
|
}
|
|
|
|
// Open the file again for writing
|
|
file = fopen(filename, "wb");
|
|
if (!file)
|
|
{
|
|
delete[] fileContent;
|
|
delete[] newContent;
|
|
return false;
|
|
}
|
|
|
|
// Write the updated content to the file
|
|
fwrite(newContent, sizeof(char), strlen(newContent), file);
|
|
|
|
// Clean up
|
|
fclose(file);
|
|
delete[] fileContent;
|
|
delete[] newContent;
|
|
|
|
return true;
|
|
} |