SettingsHandler: Don't output null bytes

https://bugs.dolphin-emu.org/issues/12019, take two.
This commit is contained in:
JosJuice 2020-03-24 16:58:54 +01:00
parent 5b10f4b71e
commit 5d6f23e424
2 changed files with 29 additions and 18 deletions

View File

@ -6,6 +6,7 @@
#include "Common/SettingsHandler.h"
#include <algorithm>
#include <cstddef>
#include <ctime>
#include <iomanip>
@ -79,12 +80,10 @@ void SettingsHandler::Decrypt()
m_key = (m_key >> 31) | (m_key << 1);
}
// Decryption done. Now get rid of all CR in the output.
// The decoded file is supposed to contain Windows line endings
// (CR-LF), but sometimes also contains CR-LF-LF endings which
// confuse the parsing code, so let's just get rid of all CR
// line endings.
// The decoded data normally uses CRLF line endings, but occasionally
// (see the comment in WriteLine), lines can be separated by CRLFLF.
// To handle this, we remove every CR and treat LF as the line ending.
// (We ignore empty lines.)
decoded.erase(std::remove(decoded.begin(), decoded.end(), '\x0d'), decoded.end());
}
@ -96,22 +95,33 @@ void SettingsHandler::Reset()
m_buffer = {};
}
void SettingsHandler::AddSetting(std::string_view key, std::string_view value)
void SettingsHandler::AddSetting(const std::string& key, const std::string& value)
{
for (const char& c : key)
{
WriteByte(c);
WriteLine(key + '=' + value + "\r\n");
}
WriteByte('=');
for (const char& c : value)
void SettingsHandler::WriteLine(const std::string& str)
{
WriteByte(c);
}
const u32 old_position = m_position;
const u32 old_key = m_key;
WriteByte(13);
WriteByte(10);
// Encode and write the line
for (char c : str)
WriteByte(c);
// If the encoded data contains a null byte, Nintendo's decoder will stop at that null byte
// instead of decoding all the data. To avoid this: If the data we just wrote contains
// a null byte, add an LF right before the line to prod the values into being different,
// just like Nintendo does. Due to the chosen key, LF itself never encodes into a null byte.
const auto begin = m_buffer.cbegin() + old_position;
const auto end = m_buffer.cbegin() + m_position;
if (std::find(begin, end, 0) != end)
{
m_key = old_key;
m_position = old_position;
WriteByte('\n');
WriteLine(str);
}
}
void SettingsHandler::WriteByte(u8 b)

View File

@ -28,7 +28,7 @@ public:
SettingsHandler();
explicit SettingsHandler(Buffer&& buffer);
void AddSetting(std::string_view key, std::string_view value);
void AddSetting(const std::string& key, const std::string& value);
const Buffer& GetBytes() const;
void SetBytes(Buffer&& buffer);
@ -39,6 +39,7 @@ public:
static std::string GenerateSerialNumber();
private:
void WriteLine(const std::string& str);
void WriteByte(u8 b);
std::array<u8, SETTINGS_SIZE> m_buffer;