Detect ISO files from file contents if extensions are wrong.

On older Android versions (that still support Android Storage
Framework), filenames are not always preserved in Content URIs, they can
look like .../msf:342 and things like that. So identify a few more file
types by content if filename identification fails.
This commit is contained in:
Henrik Rydgård 2022-04-30 17:47:17 +02:00
parent 81852b5f8b
commit d4dedeeeb8
3 changed files with 26 additions and 0 deletions

View File

@ -126,6 +126,9 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
return IdentifiedFileType::NORMAL_DIRECTORY; return IdentifiedFileType::NORMAL_DIRECTORY;
} }
// OK, quick methods of identification for common types failed. Moving on to more expensive methods,
// starting by reading the first few bytes.
u32_le id; u32_le id;
size_t readSize = fileLoader->ReadAt(0, 4, 1, &id); size_t readSize = fileLoader->ReadAt(0, 4, 1, &id);
@ -141,8 +144,28 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
} else if (!memcmp(&_id, "\x00PBP", 4)) { } else if (!memcmp(&_id, "\x00PBP", 4)) {
fileLoader->ReadAt(0x24, 4, 1, &psar_offset); fileLoader->ReadAt(0x24, 4, 1, &psar_offset);
fileLoader->ReadAt(psar_offset, 4, 1, &psar_id); fileLoader->ReadAt(psar_offset, 4, 1, &psar_id);
// Fall through to the below if chain.
} else if (!memcmp(&_id, "Rar!", 4)) { } else if (!memcmp(&_id, "Rar!", 4)) {
return IdentifiedFileType::ARCHIVE_RAR; return IdentifiedFileType::ARCHIVE_RAR;
} else if (!memcmp(&_id, "\x37\x7A\xBC\xAF", 4)) {
return IdentifiedFileType::ARCHIVE_7Z;
} else if (!memcmp(&_id, "\0\0\0\0", 4)) {
// All zeroes. ISO files start like this but their 16th 2048-byte sector contains metadata.
if (fileLoader->FileSize() > 0x8100) {
char buffer[16];
fileLoader->ReadAt(0x8000, sizeof(buffer), buffer);
if (!memcmp(buffer + 1, "CD001", 5)) {
// It's an ISO file.
if (!memcmp(buffer + 8, "PSP GAME", 8)) {
return IdentifiedFileType::PSP_ISO;
}
return IdentifiedFileType::UNKNOWN_ISO;
}
}
} else if (!memcmp(&_id, "CISO", 4)) {
// CISO are not used for many other kinds of ISO so let's just guess it's a PSP one and let it
// fail later...
return IdentifiedFileType::PSP_ISO;
} }
if (id == 'FLE\x7F') { if (id == 'FLE\x7F') {
@ -337,6 +360,7 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
case IdentifiedFileType::UNKNOWN_BIN: case IdentifiedFileType::UNKNOWN_BIN:
case IdentifiedFileType::UNKNOWN_ELF: case IdentifiedFileType::UNKNOWN_ELF:
case IdentifiedFileType::UNKNOWN_ISO:
case IdentifiedFileType::UNKNOWN: case IdentifiedFileType::UNKNOWN:
ERROR_LOG(LOADER, "Unknown file type: %s (%s)", fileLoader->GetPath().c_str(), error_string->c_str()); ERROR_LOG(LOADER, "Unknown file type: %s (%s)", fileLoader->GetPath().c_str(), error_string->c_str());
*error_string = "Unknown file type: " + fileLoader->GetPath().ToString(); *error_string = "Unknown file type: " + fileLoader->GetPath().ToString();

View File

@ -37,6 +37,7 @@ enum class IdentifiedFileType {
UNKNOWN_BIN, UNKNOWN_BIN,
UNKNOWN_ELF, UNKNOWN_ELF,
UNKNOWN_ISO,
// Try to reduce support emails... // Try to reduce support emails...
ARCHIVE_RAR, ARCHIVE_RAR,

View File

@ -83,6 +83,7 @@ bool GameInfo::Delete() {
case IdentifiedFileType::PSP_ELF: case IdentifiedFileType::PSP_ELF:
case IdentifiedFileType::UNKNOWN_BIN: case IdentifiedFileType::UNKNOWN_BIN:
case IdentifiedFileType::UNKNOWN_ELF: case IdentifiedFileType::UNKNOWN_ELF:
case IdentifiedFileType::UNKNOWN_ISO:
case IdentifiedFileType::ARCHIVE_RAR: case IdentifiedFileType::ARCHIVE_RAR:
case IdentifiedFileType::ARCHIVE_ZIP: case IdentifiedFileType::ARCHIVE_ZIP:
case IdentifiedFileType::ARCHIVE_7Z: case IdentifiedFileType::ARCHIVE_7Z: