Skip to content

Commit

Permalink
Validate API data before using & minor bug fix
Browse files Browse the repository at this point in the history
  • Loading branch information
CompSciOrBust committed Aug 22, 2022
1 parent 2e901bf commit a1f39b6
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 30 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ INCLUDES := include Arriba/include json/single_include zipper/zipper
ROMFS := romfs
APP_TITLE := Amiigo
APP_AUTHOR := CompSciOrBust
APP_VERSION := 2.3.0
APP_VERSION := 2.3.1

#---------------------------------------------------------------------------------
# options for code generation
Expand Down
3 changes: 1 addition & 2 deletions include/Networking.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <string>
#include <switch.h>

std::size_t curlWriteFile(const char* in, std::size_t size, std::size_t num, FILE* out);
bool retrieveToFile(std::string URL, std::string path);
std::string retrieveToString(std::string URL, std::string mimeType);
bool retrieveToString(std::string URL, std::string mimeType, std::string *out);
bool hasNetworkConnection();
2 changes: 2 additions & 0 deletions source/AmiigoUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace Amiigo::UI

void initSplash()
{
Arriba::activeLayer++;
splashScene = new Arriba::Primitives::Quad(0, 0, Arriba::Graphics::windowWidth, Arriba::Graphics::windowHeight, Arriba::Graphics::Pivot::topLeft);
splashScene->setColour({0.25,0.25,0.25,0.95});
//Title text
Expand Down Expand Up @@ -73,6 +74,7 @@ namespace Amiigo::UI
splashScene->destroy();
if(settingsScene) settingsScene->enabled = true;
if(sceneSwitcher) sceneSwitcher->enabled = true;
Arriba::activeLayer--;
}

void initSceneSwitcher()
Expand Down
33 changes: 22 additions & 11 deletions source/Networking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
#include <curl/curl.h>
#include <string>
#include <switch.h>

#include <fstream>

bool retrieveToFile(std::string URL, std::string path)
{
if(!hasNetworkConnection()) return false;
FILE* file = fopen(path.c_str(), "wb");
std::ofstream file(path.c_str(), std::ofstream::trunc | std::ofstream::binary);
if(file)
{
CURL *curl = curl_easy_init();
Expand All @@ -17,21 +17,27 @@ bool retrieveToFile(std::string URL, std::string path)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, +[](const char* in, std::size_t size, std::size_t num, FILE* out){
fwrite(in, size, num, out);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, +[](const char* in, std::size_t size, std::size_t num, std::ofstream* out){
out->write(in, size * num);
return (size * num);
});
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
curl_easy_perform(curl);
CURLcode errorCode = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if(errorCode != CURLE_OK)
{
printf("ERROR: failed to download %s to %s\nCurl error code:%d\n", URL.c_str(), path.c_str(), errorCode);
file.close();
return false;
}
}
fclose(file);
file.close();
return true;
}

//https://github.com/XorTroll/Goldleaf/blob/e1f5f9f9c797911e1902df37df2f0cdcc8940868/Goldleaf/source/net/net_Network.cpp#L48
std::string retrieveToString(std::string URL, std::string mimeType)
bool retrieveToString(std::string URL, std::string mimeType, std::string *out)
{
CURL *curl = curl_easy_init();
if(!mimeType.empty())
Expand All @@ -53,10 +59,15 @@ std::string retrieveToString(std::string URL, std::string mimeType)
out->append(in, total_size);
return total_size;
});
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);
curl_easy_perform(curl);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, out);
CURLcode errorCode = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return content;
if(errorCode != CURLE_OK)
{
printf("ERROR: failed to download %s\nCurl error code:%d\n", URL.c_str(), errorCode);
return false;
}
return true;
}

bool hasNetworkConnection()
Expand Down
56 changes: 42 additions & 14 deletions source/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,15 @@ std::vector<std::string> getListOfSeries()
{
APIData += tempLine;
}
nlohmann::json APIJson = nlohmann::json::parse(APIData);
fileStream.close();
nlohmann::json APIJson = nlohmann::json::parse(APIData, nullptr, false);
//Check API cache is valid
if(APIJson.is_discarded())
{
printf("API cache is corrupt\n");
remove("sdmc:/config/amiigo/API.json");
return {"Error, API cache corrupt!", "Try updating cache in settings!"};
}
//Loop over every entry under the Amiibo object
for (int i = 0; i < APIJson["amiibo"].size(); i++)
{
Expand Down Expand Up @@ -272,20 +279,31 @@ void firstTimeSetup()
}
else if(!retrieveToFile("https://www.amiiboapi.com/api/amiibo", "sdmc:/config/amiigo/API.tmp")) continue;
rename("sdmc:/config/amiigo/API.tmp", "sdmc:/config/amiigo/API.json");
//Check file isn't empty
//Check file is valid JSOB
std::string apiLine = "";
std::string tempLine = "";
std::ifstream apiStream("sdmc:/config/amiigo/API.json");
getline(apiStream, apiLine);
while(getline(apiStream, tempLine)) apiLine += tempLine;
apiStream.close();
if(apiLine.size() == 0) remove("sdmc:/config/amiigo/API.json");
if(!nlohmann::json::accept(apiLine)) remove("sdmc:/config/amiigo/API.json");
}
//Install emuiibo
if(!checkIfFileExists("sdmc:/atmosphere/contents/0100000000000352/exefs.nsp"))
{
while(!hasNetworkConnection());
if(checkIfFileExists("sdmc:/config/amiigo/emuiibo.tmp")) remove("sdmc:/config/amiigo/emuiibo.tmp");
std::string emuiiboReleaseInfo = retrieveToString("https://api.github.com/repos/XorTroll/Emuiibo/releases", "application/json");
nlohmann::json emuiiboInfo = nlohmann::json::parse(emuiiboReleaseInfo);
bool hasValidEmuiiboJSON = false;
nlohmann::json emuiiboInfo;
while (!hasValidEmuiiboJSON)
{
printf("Downloading Emuiibo zip\n");
while(!hasNetworkConnection());
if(checkIfFileExists("sdmc:/config/amiigo/emuiibo.tmp")) remove("sdmc:/config/amiigo/emuiibo.tmp");
//We should probably do this in a more robust way
std::string emuiiboReleaseInfo;
while(!retrieveToString("https://api.github.com/repos/XorTroll/Emuiibo/releases", "application/json", &emuiiboReleaseInfo));
emuiiboInfo = nlohmann::json::parse(emuiiboReleaseInfo, nullptr, false);
hasValidEmuiiboJSON = !emuiiboInfo.is_discarded();
}
printf("hasValidEmuiiboJSON: %d\n", hasValidEmuiiboJSON);
while(!retrieveToFile(emuiiboInfo[0]["assets"][0]["browser_download_url"].get<std::string>().c_str(), "sdmc:/config/amiigo/emuiibo.tmp"));
printf("Unzipping\n");
//Extract the files from the emuiibo zip
Expand All @@ -303,6 +321,7 @@ void firstTimeSetup()
unz_file_info fileInfo;
unzOpenCurrentFile(zipFile);
unzGetCurrentFileInfo(zipFile, &fileInfo, fileName, sizeof(fileName), nullptr, 0, nullptr, 0);
printf("Zip index:%d is %s\n", i, fileName);
if(strcmp("SdOut/atmosphere/contents/0100000000000352/exefs.nsp", fileName) == 0)
{
void* buffer = malloc(500000);
Expand All @@ -318,6 +337,7 @@ void firstTimeSetup()
unzCloseCurrentFile(zipFile);
unzGoToNextFile(zipFile);
}
printf("Unzip done\n");
unzClose(zipFile);
remove("sdmc:/config/amiigo/emuiibo.tmp");
//Launch the sysmodule
Expand All @@ -330,8 +350,8 @@ void firstTimeSetup()
if(checkIfFileExists("sdmc:/config/amiigo/update.flag"))
{
while(!hasNetworkConnection());
retrieveToFile(Amiigo::Settings::updateURL, "sdmc:/switch/Failed_Amiigo_Update.nro");
if(checkIfFileExists("sdmc:/switch/Failed_Amiigo_Update.nro"))
bool DLSuccess = retrieveToFile(Amiigo::Settings::updateURL, "sdmc:/switch/Failed_Amiigo_Update.nro");
if(checkIfFileExists("sdmc:/switch/Failed_Amiigo_Update.nro") && DLSuccess)
{
romfsExit();
if(checkIfFileExists(Amiigo::Settings::amiigoPath)) remove(Amiigo::Settings::amiigoPath);
Expand Down Expand Up @@ -364,14 +384,22 @@ bool checkForUpdates()
return false;
}
printf("Getting API data\n");
std::string amiigoReleaseInfo = retrieveToString("https://api.github.com/repos/CompSciOrBust/Amiigo/releases", "application/json");
if(amiigoReleaseInfo.size() < 300) //User is probably being rate limited
std::string amiigoReleaseInfo;
bool releaseInfoSuccess = retrieveToString("https://api.github.com/repos/CompSciOrBust/Amiigo/releases", "application/json", &amiigoReleaseInfo);
if(amiigoReleaseInfo.size() < 300 || !releaseInfoSuccess) //User is probably being rate limited
{
printf("%s\n", amiigoReleaseInfo.c_str());
printf("Error, getting Amiigo update info failed\n");
return false;
}
nlohmann::json amiigoInfoParsed = nlohmann::json::parse(amiigoReleaseInfo, nullptr, false);
//If data is corrupt do nothing
if(amiigoInfoParsed.is_discarded())
{
printf("%s\n", amiigoReleaseInfo.c_str());
printf("Error, sub 300\n");
printf("Error, Amiigo update info corrupt\n");
return false;
}
nlohmann::json amiigoInfoParsed = nlohmann::json::parse(amiigoReleaseInfo);
//If on the latest update wait another 24 hours before checking again
if(amiigoInfoParsed[0]["tag_name"].get<std::string>() == VERSION)
{
Expand Down
3 changes: 1 addition & 2 deletions source/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ int main(int argc, char *argv[])
//Init UI
Amiigo::UI::initUI();
if(emu::IsAvailable()) emu::Initialize();
//if(!checkIfFileExists("sdmc:/config/amiigo/API.json"))retrieveToFile("https://www.amiiboapi.com/api/amiibo", "sdmc:/config/amiigo/API.json");

//Main loop
while (appletMainLoop())
Expand All @@ -45,6 +44,6 @@ int main(int argc, char *argv[])
romfsExit();
nifmExit();
Arriba::exit();
if(emu::IsAvailable) emu::Exit();
if(emu::IsAvailable()) emu::Exit();
return 0;
}

0 comments on commit a1f39b6

Please sign in to comment.