Merge branch 'lh_ini_null_chars'
This commit is contained in:
commit
da6170d721
@ -230,8 +230,13 @@ static std::string appconfig_md5_hash_line(const std::string_view data)
|
||||
return "# MD5 checksum " + md5_digest_str + "\n";
|
||||
};
|
||||
|
||||
struct ConfigFileInfo {
|
||||
bool correct_checksum {false};
|
||||
bool contains_null {false};
|
||||
};
|
||||
|
||||
// Assume that the last line with the comment inside the config file contains a checksum and that the user didn't modify the config file.
|
||||
static bool verify_config_file_checksum(boost::nowide::ifstream &ifs)
|
||||
static ConfigFileInfo check_config_file_and_verify_checksum(boost::nowide::ifstream &ifs)
|
||||
{
|
||||
auto read_whole_config_file = [&ifs]() -> std::string {
|
||||
std::stringstream ss;
|
||||
@ -240,7 +245,8 @@ static bool verify_config_file_checksum(boost::nowide::ifstream &ifs)
|
||||
};
|
||||
|
||||
ifs.seekg(0, boost::nowide::ifstream::beg);
|
||||
std::string whole_config = read_whole_config_file();
|
||||
const std::string whole_config = read_whole_config_file();
|
||||
const bool contains_null = whole_config.find_first_of('\0') != std::string::npos;
|
||||
|
||||
// The checksum should be on the last line in the config file.
|
||||
if (size_t last_comment_pos = whole_config.find_last_of('#'); last_comment_pos != std::string::npos) {
|
||||
@ -249,9 +255,9 @@ static bool verify_config_file_checksum(boost::nowide::ifstream &ifs)
|
||||
// When the checksum isn't found, the checksum was not saved correctly, it was removed or it is an older config file without the checksum.
|
||||
// If the checksum is incorrect, then the file was either not saved correctly or modified.
|
||||
if (std::string_view(whole_config.c_str() + last_comment_pos, whole_config.size() - last_comment_pos) == appconfig_md5_hash_line({ whole_config.data(), last_comment_pos }))
|
||||
return true;
|
||||
return {true, contains_null};
|
||||
}
|
||||
return false;
|
||||
return {false, contains_null};
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -269,14 +275,25 @@ std::string AppConfig::load(const std::string &path)
|
||||
ifs.open(path);
|
||||
#ifdef WIN32
|
||||
// Verify the checksum of the config file without taking just for debugging purpose.
|
||||
if (!verify_config_file_checksum(ifs))
|
||||
BOOST_LOG_TRIVIAL(info) << "The configuration file " << path <<
|
||||
" has a wrong MD5 checksum or the checksum is missing. This may indicate a file corruption or a harmless user edit.";
|
||||
const ConfigFileInfo config_file_info = check_config_file_and_verify_checksum(ifs);
|
||||
if (!config_file_info.correct_checksum)
|
||||
BOOST_LOG_TRIVIAL(info)
|
||||
<< "The configuration file " << path
|
||||
<< " has a wrong MD5 checksum or the checksum is missing. This may indicate a file corruption or a harmless user edit.";
|
||||
|
||||
if (!config_file_info.correct_checksum && config_file_info.contains_null) {
|
||||
BOOST_LOG_TRIVIAL(info) << "The configuration file " + path + " is corrupted, because it is contains null characters.";
|
||||
throw Slic3r::CriticalException("The configuration file contains null characters.");
|
||||
}
|
||||
|
||||
ifs.seekg(0, boost::nowide::ifstream::beg);
|
||||
#endif
|
||||
pt::read_ini(ifs, tree);
|
||||
} catch (pt::ptree_error& ex) {
|
||||
try {
|
||||
pt::read_ini(ifs, tree);
|
||||
} catch (pt::ptree_error &ex) {
|
||||
throw Slic3r::CriticalException(ex.what());
|
||||
}
|
||||
} catch (Slic3r::CriticalException &ex) {
|
||||
#ifdef WIN32
|
||||
// The configuration file is corrupted, try replacing it with the backup configuration.
|
||||
ifs.close();
|
||||
@ -284,29 +301,29 @@ std::string AppConfig::load(const std::string &path)
|
||||
if (boost::filesystem::exists(backup_path)) {
|
||||
// Compute checksum of the configuration backup file and try to load configuration from it when the checksum is correct.
|
||||
boost::nowide::ifstream backup_ifs(backup_path);
|
||||
if (!verify_config_file_checksum(backup_ifs)) {
|
||||
BOOST_LOG_TRIVIAL(error) << format("Both \"%1%\" and \"%2%\" are corrupted. It isn't possible to restore configuration from the backup.", path, backup_path);
|
||||
if (const ConfigFileInfo config_file_info = check_config_file_and_verify_checksum(backup_ifs); !config_file_info.correct_checksum || config_file_info.contains_null) {
|
||||
BOOST_LOG_TRIVIAL(error) << format(R"(Both "%1%" and "%2%" are corrupted. It isn't possible to restore configuration from the backup.)", path, backup_path);
|
||||
backup_ifs.close();
|
||||
boost::filesystem::remove(backup_path);
|
||||
} else if (std::string error_message; copy_file(backup_path, path, error_message, false) != SUCCESS) {
|
||||
BOOST_LOG_TRIVIAL(error) << format("Configuration file \"%1%\" is corrupted. Failed to restore from backup \"%2%\": %3%", path, backup_path, error_message);
|
||||
BOOST_LOG_TRIVIAL(error) << format(R"(Configuration file "%1%" is corrupted. Failed to restore from backup "%2%": %3%)", path, backup_path, error_message);
|
||||
backup_ifs.close();
|
||||
boost::filesystem::remove(backup_path);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << format("Configuration file \"%1%\" was corrupted. It has been succesfully restored from the backup \"%2%\".", path, backup_path);
|
||||
BOOST_LOG_TRIVIAL(info) << format(R"(Configuration file "%1%" was corrupted. It has been successfully restored from the backup "%2%".)", path, backup_path);
|
||||
// Try parse configuration file after restore from backup.
|
||||
try {
|
||||
ifs.open(path);
|
||||
pt::read_ini(ifs, tree);
|
||||
recovered = true;
|
||||
} catch (pt::ptree_error& ex) {
|
||||
BOOST_LOG_TRIVIAL(info) << format("Failed to parse configuration file \"%1%\" after it has been restored from backup: %2%", path, ex.what());
|
||||
BOOST_LOG_TRIVIAL(info) << format(R"(Failed to parse configuration file "%1%" after it has been restored from backup: %2%)", path, ex.what());
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif // WIN32
|
||||
BOOST_LOG_TRIVIAL(info) << format("Failed to parse configuration file \"%1%\": %2%", path, ex.what());
|
||||
if (! recovered) {
|
||||
BOOST_LOG_TRIVIAL(info) << format(R"(Failed to parse configuration file "%1%": %2%)", path, ex.what());
|
||||
if (!recovered) {
|
||||
// Report the initial error of parsing PrusaSlicer.ini.
|
||||
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
|
||||
// ! But to avoid the use of _utf8 (related to use of wxWidgets)
|
||||
|
Loading…
Reference in New Issue
Block a user