Improved checking if a file is a plugin.

Closes #322.
This commit is contained in:
Oliver Hamlet
2014-11-02 13:03:39 +00:00
parent 658886ec4f
commit d582428d4a
7 changed files with 43 additions and 23 deletions
+33 -1
View File
@@ -676,7 +676,7 @@ namespace loot {
std::vector<Plugin*> groupPlugins;
//First calculate the mean plugin size. Store it temporarily in a map to reduce filesystem lookups and file size recalculation.
for (fs::directory_iterator it(this->DataPath()); it != fs::directory_iterator(); ++it) {
if (fs::is_regular_file(it->status()) && IsPlugin(it->path().string())) {
if (fs::is_regular_file(it->status()) && this->IsValidPlugin(it->path().filename().string())) {
uintmax_t fileSize = fs::file_size(it->path());
meanFileSize += fileSize;
@@ -741,6 +741,38 @@ namespace loot {
return false;
}
bool Game::IsValidPlugin(const std::string& name) const {
BOOST_LOG_TRIVIAL(trace) << "Checking to see if \"" << name << "\" is a valid plugin.";
// Rather than just checking the extension, try also parsing the file header, and see if it fails.
if (!boost::iends_with(name, ".esm") && !boost::iends_with(name, ".esp") && !boost::iends_with(name, ".esm.ghost") && !boost::iends_with(name, ".esp.ghost")) {
BOOST_LOG_TRIVIAL(warning) << "The .es(p|m) file \"" << name << "\" is not a valid plugin.";
return false;
}
try {
string filepath = (this->DataPath() / name).string();
if (fs::exists(this->DataPath() / fs::path(name + ".ghost")))
filepath += ".ghost";
espm::File * file = nullptr;
if (this->Id() == LIBLO_GAME_TES4)
file = new espm::tes4::File(filepath, this->espm_settings, false, true);
else if (this->Id() == LIBLO_GAME_TES5)
file = new espm::tes5::File(filepath, this->espm_settings, false, true);
else if (this->Id() == LIBLO_GAME_FO3)
file = new espm::fo3::File(filepath, this->espm_settings, false, true);
else
file = new espm::fonv::File(filepath, this->espm_settings, false, true);
delete file;
}
catch (std::exception& /*e*/) {
BOOST_LOG_TRIVIAL(warning) << "The .es(p|m) file \"" << name << "\" is not a valid plugin.";
return false;
}
return true;
}
void Game::CreateLOOTGameFolder() {
//Make sure that the LOOT game path exists.
try {
+2
View File
@@ -141,6 +141,8 @@ namespace loot {
void LoadPlugins(bool headersOnly); //Loads all installed plugins.
bool HasBeenLoaded(); // Checks if the game's plugins have already been loaded.
bool IsValidPlugin(const std::string& name) const;
std::list<Plugin> Sort(const unsigned int language, std::function<void(const std::string&)> progressCallback);
//Caches for condition results, active plugins and CRCs.
+2 -4
View File
@@ -179,8 +179,7 @@ namespace loot {
BOOST_LOG_TRIVIAL(trace) << "Adding in-edges for requirements.";
set<File> fileset(graph[*vit].Reqs());
for (const auto &file : fileset) {
if (loot::IsPlugin(file.Name()) &&
loot::GetVertexByName(graph, file.Name(), parentVertex) &&
if (loot::GetVertexByName(graph, file.Name(), parentVertex) &&
!boost::edge(parentVertex, *vit, graph).second) {
BOOST_LOG_TRIVIAL(trace) << "Adding edge from \"" << graph[parentVertex].Name() << "\" to \"" << graph[*vit].Name() << "\".";
@@ -196,8 +195,7 @@ namespace loot {
BOOST_LOG_TRIVIAL(trace) << "Adding in-edges for 'load after's.";
fileset = graph[*vit].LoadAfter();
for (const auto &file : fileset) {
if (loot::IsPlugin(file.Name()) &&
loot::GetVertexByName(graph, file.Name(), parentVertex) &&
if (loot::GetVertexByName(graph, file.Name(), parentVertex) &&
!boost::edge(parentVertex, *vit, graph).second) {
BOOST_LOG_TRIVIAL(trace) << "Adding edge from \"" << graph[parentVertex].Name() << "\" to \"" << graph[*vit].Name() << "\".";
+2 -10
View File
@@ -862,13 +862,13 @@ namespace loot {
}
}
for (const auto &req : requirements) {
if (!boost::filesystem::exists(game.DataPath() / req.Name()) && !(IsPlugin(req.Name()) && boost::filesystem::exists(game.DataPath() / (req.Name() + ".ghost")))) {
if (!boost::filesystem::exists(game.DataPath() / req.Name()) && !((boost::iends_with(req.Name(), ".esp") || boost::iends_with(req.Name(), ".esm")) && boost::filesystem::exists(game.DataPath() / (req.Name() + ".ghost")))) {
BOOST_LOG_TRIVIAL(error) << "\"" << name << "\" requires \"" << req.Name() << "\", but it is missing.";
messages.push_back(loot::Message(messageType, (boost::format(boost::locale::translate("This plugin requires \"%1%\" to be installed, but it is missing.")) % req.Name()).str()));
}
}
for (const auto &inc : incompatibilities) {
if (boost::filesystem::exists(game.DataPath() / inc.Name()) || (IsPlugin(inc.Name()) && boost::filesystem::exists(game.DataPath() / (inc.Name() + ".ghost")))) {
if (boost::filesystem::exists(game.DataPath() / inc.Name()) || ((boost::iends_with(inc.Name(), ".esp") || boost::iends_with(inc.Name(), ".esm")) && boost::filesystem::exists(game.DataPath() / (inc.Name() + ".ghost")))) {
if (!game.IsActive(inc.Name()))
messageType = loot::Message::warn;
BOOST_LOG_TRIVIAL(error) << "\"" << name << "\" is incompatible with \"" << inc.Name() << "\", but both are present.";
@@ -928,12 +928,4 @@ namespace loot {
bool operator == (const Plugin& lhs, const std::string& rhs) {
return rhs == lhs;
}
bool IsPlugin(const std::string& file) {
if (boost::iends_with(file, ".esp") || boost::iends_with(file, ".esm")
|| boost::iends_with(file, ".esp.ghost") || boost::iends_with(file, ".esm.ghost"))
return true;
else
return false;
}
}
-2
View File
@@ -273,8 +273,6 @@ namespace loot {
bool operator == (const Plugin& lhs, const File& rhs);
bool operator == (const std::string& lhs, const Plugin& rhs);
bool IsPlugin(const std::string& file);
}
namespace std {
+3 -3
View File
@@ -540,7 +540,7 @@ namespace loot {
throw loot::error(loot::error::invalid_args, boost::locale::translate("Invalid file path:").str() + " " + file);
}
if (IsPlugin(file))
if (boost::iends_with(file, ".esp") || boost::iends_with(file, ".esm"))
result = boost::filesystem::exists(_game->DataPath() / file) || boost::filesystem::exists(_game->DataPath() / (file + ".ghost"));
else
result = boost::filesystem::exists(_game->DataPath() / file);
@@ -642,7 +642,7 @@ namespace loot {
crc = GetCrc32(boost::filesystem::absolute("LOOT.exe"));
if (boost::filesystem::exists(_game->DataPath() / file))
crc = GetCrc32(_game->DataPath() / file);
else if (IsPlugin(file) && boost::filesystem::exists(_game->DataPath() / (file + ".ghost")))
else if ((boost::iends_with(file, ".esp") || boost::iends_with(file, ".esm")) && boost::filesystem::exists(_game->DataPath() / (file + ".ghost")))
crc = GetCrc32(_game->DataPath() / (file + ".ghost"));
else {
result = false;
@@ -673,7 +673,7 @@ namespace loot {
Version trueVersion;
if (file == "LOOT")
trueVersion = Version(boost::filesystem::absolute("LOOT.exe"));
else if (IsPlugin(file)) {
else if (_game->IsValidPlugin(file)) {
Plugin plugin(*_game, file, true);
trueVersion = Version(plugin.Version());
}
+1 -3
View File
@@ -209,8 +209,6 @@ TEST_F(OblivionAPIOperationsTest, SortPlugins) {
"Oblivion.esm",
"Blank - Different.esm",
"Blank - Different Master Dependent.esm",
"NotAPlugin.esm",
"EmptyFile.esm",
"Blank - Master Dependent.esp",
"Blank.esp",
"Blank - Plugin Dependent.esp",
@@ -222,7 +220,7 @@ TEST_F(OblivionAPIOperationsTest, SortPlugins) {
for (size_t i = 0; i < numPlugins; ++i) {
actualOrder.push_back(sortedPlugins[i]);
}
EXPECT_EQ(13, numPlugins);
EXPECT_EQ(11, numPlugins);
EXPECT_EQ(expectedOrder, actualOrder);
}
#endif