AdrenoTools: Fix picking zip files from the Downloads folder. Add more validation.

This commit is contained in:
Henrik Rydgård 2024-01-15 11:46:41 +01:00
parent 0caebbfaa6
commit 8faba8426a
8 changed files with 90 additions and 58 deletions

View File

@ -10,8 +10,7 @@
namespace json {
struct JsonGet {
JsonGet(const JsonValue &value) : value_(value) {
}
JsonGet(const JsonValue &value) : value_(value) {}
int numChildren() const;
const JsonNode *get(const char *child_name) const;
@ -47,7 +46,8 @@ struct JsonGet {
class JsonReader {
public:
JsonReader(const std::string &filename);
JsonReader(const void *data, size_t size) {
// Makes a copy, after this returns you can free the input buffer.
JsonReader(const char *data, size_t size) {
buffer_ = (char *)malloc(size + 1);
if (buffer_) {
memcpy(buffer_, data, size);

View File

@ -91,6 +91,7 @@ enum class BrowseFileType {
INI,
DB,
SOUND_EFFECT,
ZIP,
ANY,
};

View File

@ -318,6 +318,9 @@ bool MainUI::HandleCustomEvent(QEvent *e) {
case BrowseFileType::SOUND_EFFECT:
filter = "WAVE files (*.wav)";
break;
case BrowseFileType::ZIP:
filter = "ZIP files (*.zip)";
break;
case BrowseFileType::ANY:
break;
}

View File

@ -1268,59 +1268,75 @@ UI::EventReturn DeveloperToolsScreen::OnCustomDriverChange(UI::EventParams &e) {
UI::EventReturn DeveloperToolsScreen::OnCustomDriverInstall(UI::EventParams &e) {
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
System_BrowseForFile(gr->T("Install Custom Driver..."), BrowseFileType::ANY, [this](const std::string &value, int) {
const Path driverPath = g_Config.internalDataDirectory / "drivers";
if (!value.empty()) {
Path zipPath = Path(value);
bool success = false;
if (zipPath.GetFileExtension() == ".zip") {
ZipFileReader *zipFileReader = ZipFileReader::Create(zipPath, "");
size_t metaDataSize;
uint8_t *metaData = zipFileReader->ReadFile("meta.json", &metaDataSize);
Path tempMeta = Path(g_Config.internalDataDirectory / "meta.json");
File::CreateEmptyFile(tempMeta);
File::WriteDataToFile(false, metaData, metaDataSize, tempMeta);
delete[] metaData;
json::JsonReader meta = json::JsonReader((g_Config.internalDataDirectory / "meta.json").c_str());
if (meta.ok()) {
std::string driverName = meta.root().get("name")->value.toString();
Path newCustomDriver = driverPath / driverName;
File::CreateFullPath(newCustomDriver);
std::vector<File::FileInfo> zipListing;
zipFileReader->GetFileListing("", &zipListing, nullptr);
for (auto file : zipListing) {
File::CreateEmptyFile(newCustomDriver / file.name);
size_t size;
uint8_t *data = zipFileReader->ReadFile(file.name.c_str(), &size);
File::WriteDataToFile(false, data, size, newCustomDriver / file.name);
delete[] data;
}
File::Delete(tempMeta);
success = true;
RecreateViews();
}
}
if (!success) {
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("The file is not a ZIP file containing a compatible driver."));
}
System_BrowseForFile(gr->T("Install Custom Driver..."), BrowseFileType::ZIP, [this](const std::string &value, int) {
if (value.empty()) {
return;
}
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
Path zipPath = Path(value);
// Don't bother checking the file extension. Can't always do that with files from Download (they have paths like content://com.android.providers.downloads.documents/document/msf%3A1000001095).
// Though, it may be possible to get it in other ways.
std::unique_ptr<ZipFileReader> zipFileReader = std::unique_ptr<ZipFileReader>(ZipFileReader::Create(zipPath, "", true));
if (!zipFileReader) {
g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("The chosen file is not a valid ZIP file."));
ERROR_LOG(SYSTEM, "Failed to open file '%s' as zip", zipPath.c_str());
return;
}
size_t metaDataSize;
uint8_t *metaData = zipFileReader->ReadFile("meta.json", &metaDataSize);
if (!metaData) {
g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("The chosen ZIP file doesn't contain a valid driver"), "meta.json missing");
return;
}
// Validate the json file. TODO: Be a bit more detailed.
json::JsonReader meta = json::JsonReader((const char *)metaData, metaDataSize);
delete[] metaData;
if (!meta.ok()) {
g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("The chosen ZIP file doesn't contain a valid driver"), "meta.json not valid json");
return;
}
const JsonNode *nameNode = meta.root().get("name");
if (!nameNode) {
g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("The chosen ZIP file doesn't contain a valid driver"), "missing driver name in json");
return;
}
std::string driverName = nameNode->value.toString();
if (driverName.empty()) {
g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("The chosen ZIP file doesn't contain a valid driver"), "driver name empty");
return;
}
const Path newCustomDriver = g_Config.internalDataDirectory / "drivers" / driverName;
NOTICE_LOG(G3D, "Installing driver into '%s'", newCustomDriver.c_str());
File::CreateFullPath(newCustomDriver);
std::vector<File::FileInfo> zipListing;
zipFileReader->GetFileListing("", &zipListing, nullptr);
for (auto file : zipListing) {
File::CreateEmptyFile(newCustomDriver / file.name);
size_t size;
uint8_t *data = zipFileReader->ReadFile(file.name.c_str(), &size);
if (!data) {
g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("The chosen ZIP file doesn't contain a valid driver"), file.name.c_str());
return;
}
File::WriteDataToFile(false, data, size, newCustomDriver / file.name);
delete[] data;
}
auto iz = GetI18NCategory(I18NCat::INSTALLZIP);
g_OSD.Show(OSDType::MESSAGE_SUCCESS, iz->T("Installed!"));
RecreateViews();
});
return UI::EVENT_DONE;
}

View File

@ -507,6 +507,9 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
case BrowseFileType::INI:
supportedExtensions = { ".ini" };
break;
case BrowseFileType::ZIP:
supportedExtensions = { ".zip" };
break;
case BrowseFileType::DB:
supportedExtensions = { ".db" };
break;

View File

@ -569,6 +569,9 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
case BrowseFileType::INI:
filter = MakeFilter(L"Ini files (*.ini)|*.ini|All files (*.*)|*.*||");
break;
case BrowseFileType::ZIP:
filter = MakeFilter(L"ZIP files (*.zip)|*.zip|All files (*.*)|*.*||");
break;
case BrowseFileType::DB:
filter = MakeFilter(L"Cheat db files (*.db)|*.db|All files (*.*)|*.*||");
break;

View File

@ -1108,12 +1108,16 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
case SystemRequestType::BROWSE_FOR_FILE:
{
BrowseFileType fileType = (BrowseFileType)param3;
std::string params = StringFromFormat("%d", requestId);
switch (fileType) {
case BrowseFileType::SOUND_EFFECT:
PushCommand("browse_file_audio", StringFromFormat("%d", requestId));
PushCommand("browse_file_audio", params);
break;
case BrowseFileType::ZIP:
PushCommand("browse_file_zip", params);
break;
default:
PushCommand("browse_file", StringFromFormat("%d", requestId));
PushCommand("browse_file", params);
break;
}
return true;

View File

@ -1409,7 +1409,7 @@ public abstract class NativeActivity extends Activity {
Log.e(TAG, e.toString());
return false;
}
} else if (command.equals("browse_file") || command.equals("browse_file_audio")) {
} else if (command.equals("browse_file") || command.equals("browse_file_audio") || command.equals("browse_file_zip")) {
try {
int requestId = Integer.parseInt(params);
int packedResultCode = packResultCode(RESULT_OPEN_DOCUMENT, requestId);
@ -1418,6 +1418,8 @@ public abstract class NativeActivity extends Activity {
intent.addCategory(Intent.CATEGORY_OPENABLE);
if (command.equals("browse_file_audio")) {
intent.setType("audio/x-wav");
} else if (command.equals("browse_file_zip")) {
intent.setType("application/zip");
} else {
intent.setType("*/*");
}