diff --git a/common/IniParser.h b/common/IniParser.h index a3f3eb1..573ab3e 100644 --- a/common/IniParser.h +++ b/common/IniParser.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -36,24 +37,20 @@ public: if (!filePath || !filePath[0]) return false; - FILE* f = nullptr; -#ifdef _MSC_VER - if (fopen_s(&f, filePath, "r") != 0 || !f) + std::ifstream f(filePath); + if (!f.is_open()) return false; -#else - f = fopen(filePath, "r"); - if (!f) - return false; -#endif + // 不再使用固定行缓冲:超过 4KB 的行(如团购授权数百个 IP 的列表)会被 + // fgets 拆成多段,第二段不带 '=' 会被 ParseLine 丢弃 → 显示截断。 + // std::getline 按行读 std::string,无长度上限。 std::string currentSection; - char line[4096]; - - while (fgets(line, sizeof(line), f)) { - ParseLine(line, currentSection); + std::string line; + while (std::getline(f, line)) { + if (!line.empty()) { + ParseLine(&line[0], currentSection); + } } - - fclose(f); return true; } @@ -76,13 +73,11 @@ public: while (lineEnd < end && *lineEnd != '\n' && *lineEnd != '\r') lineEnd++; - // 复制行内容 + // 不再限制行长度(原 4096 上限会悄无声息地丢弃长行) size_t lineLen = lineEnd - p; - if (lineLen > 0 && lineLen < 4096) { - char line[4096]; - memcpy(line, p, lineLen); - line[lineLen] = '\0'; - ParseLine(line, currentSection); + if (lineLen > 0) { + std::string line(p, lineLen); + ParseLine(&line[0], currentSection); } // 跳过换行符 @@ -100,24 +95,17 @@ public: if (!filePath || !filePath[0]) return false; - FILE* f = nullptr; -#ifdef _MSC_VER - if (fopen_s(&f, filePath, "r") != 0 || !f) + std::ifstream f(filePath); + if (!f.is_open()) return false; -#else - f = fopen(filePath, "r"); - if (!f) - return false; -#endif std::string currentSection; - char line[4096]; - - while (fgets(line, sizeof(line), f)) { - ParseLine(line, currentSection); + std::string line; + while (std::getline(f, line)) { + if (!line.empty()) { + ParseLine(&line[0], currentSection); + } } - - fclose(f); return true; } diff --git a/common/iniFile.h b/common/iniFile.h index 3245c55..7205461 100644 --- a/common/iniFile.h +++ b/common/iniFile.h @@ -208,9 +208,25 @@ public: virtual std::string GetStr(const std::string& MainKey, const std::string& SubKey, const std::string& def = "") { - char buf[4096] = { 0 }; // 增大缓冲区以支持较长的值(如 IP 列表) - DWORD n = ::GetPrivateProfileStringA(MainKey.c_str(), SubKey.c_str(), def.c_str(), buf, sizeof(buf), m_IniFilePath); - return std::string(buf); + // 动态扩容读取:GetPrivateProfileStringA 在缓冲不够时会从中间截断, + // 必须以"是否返回 bufSize-1"判断截断并翻倍重读,否则长值(如团购授权的 + // IP 列表)会被悄无声息地切断,且后续 read-modify-write 把截断结果写回时 + // 造成永久数据丢失。 + DWORD bufSize = 4096; + const DWORD kMaxBufSize = 1024 * 1024; // 1MB 兜底,避免失控 + std::vector buf; + for (;;) { + buf.assign(bufSize, 0); + DWORD n = ::GetPrivateProfileStringA(MainKey.c_str(), SubKey.c_str(), + def.c_str(), buf.data(), bufSize, + m_IniFilePath); + // 未截断:n < bufSize - 1 + if (n + 1 < bufSize || bufSize >= kMaxBufSize) { + return std::string(buf.data(), n); + } + bufSize *= 2; + if (bufSize > kMaxBufSize) bufSize = kMaxBufSize; + } } virtual bool SetStr(const std::string& MainKey, const std::string& SubKey, const std::string& Data)