summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorshuffle2 <godisgovernment@gmail.com>2017-06-05 20:00:30 -0700
committerGitHub <noreply@github.com>2017-06-05 20:00:30 -0700
commit3fed604ad9d4004fe4bd7b1d8c971bc984056e37 (patch)
treed6bdc12e8b66efb225793941c7663c19cdf42a24 /Source/Core
parent4c8f8c011ea93b5397cc1247df20c10c3dce99d7 (diff)
parent2fd63ffa9fe772c87a06478aaed3258765c27a7e (diff)
Merge pull request #4878 from ligfx/geckodownloadcodes
Move GeckoCodeDiag download logic to GeckoCodeConfig (and make it use Curl)
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/GeckoCodeConfig.cpp143
-rw-r--r--Source/Core/Core/GeckoCodeConfig.h2
-rw-r--r--Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp164
3 files changed, 172 insertions, 137 deletions
diff --git a/Source/Core/Core/GeckoCodeConfig.cpp b/Source/Core/Core/GeckoCodeConfig.cpp
index 541537f3a4..b3139e4945 100644
--- a/Source/Core/Core/GeckoCodeConfig.cpp
+++ b/Source/Core/Core/GeckoCodeConfig.cpp
@@ -2,17 +2,158 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
+#include "Core/GeckoCodeConfig.h"
+
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
+#include <curl/curl.h>
+
#include "Common/IniFile.h"
+#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
-#include "Core/GeckoCodeConfig.h"
namespace Gecko
{
+static size_t DownloadCodesWriteCallback(void* contents, size_t size, size_t nmemb,
+ std::string* body)
+{
+ size_t realsize = size * nmemb;
+ body->insert(body->end(), reinterpret_cast<char*>(contents),
+ reinterpret_cast<char*>(contents) + realsize);
+ return realsize;
+}
+
+std::vector<GeckoCode> DownloadCodes(std::string gameid, bool* succeeded)
+{
+ switch (gameid[0])
+ {
+ case 'R':
+ case 'S':
+ case 'G':
+ break;
+ default:
+ // All channels (WiiWare, VirtualConsole, etc) are identified by their first four characters
+ gameid = gameid.substr(0, 4);
+ break;
+ }
+
+ std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> curl{curl_easy_init(), curl_easy_cleanup};
+
+ std::string endpoint{"http://geckocodes.org/txt.php?txt=" + gameid};
+ curl_easy_setopt(curl.get(), CURLOPT_URL, endpoint.c_str());
+ curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, 5);
+ std::string response_body;
+ curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, DownloadCodesWriteCallback);
+ curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &response_body);
+
+ *succeeded = true;
+ CURLcode res = curl_easy_perform(curl.get());
+ if (res != CURLE_OK)
+ {
+ ERROR_LOG(COMMON, "DownloadCodes: Curl error: %s", curl_easy_strerror(res));
+ *succeeded = false;
+ return {};
+ }
+ long response_code{0};
+ curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &response_code);
+ if (response_code != 200)
+ {
+ WARN_LOG(COMMON, "DownloadCodes: Curl response code: %li", response_code);
+ *succeeded = false;
+ return {};
+ }
+
+ // temp vector containing parsed codes
+ std::vector<GeckoCode> gcodes;
+
+ // parse the codes
+ std::istringstream ss(response_body);
+
+ std::string line;
+
+ // seek past the header, get to the first code
+ std::getline(ss, line);
+ std::getline(ss, line);
+ std::getline(ss, line);
+
+ int read_state = 0;
+ GeckoCode gcode;
+
+ while ((std::getline(ss, line).good()))
+ {
+ // Remove \r at the end of the line for files using windows line endings, std::getline only
+ // removes \n
+ line = StripSpaces(line);
+
+ if (line.empty())
+ {
+ // add the code
+ if (gcode.codes.size())
+ gcodes.push_back(gcode);
+ gcode = GeckoCode();
+ read_state = 0;
+ continue;
+ }
+
+ switch (read_state)
+ {
+ // read new code
+ case 0:
+ {
+ std::istringstream ssline(line);
+ // stop at [ character (beginning of contributor name)
+ std::getline(ssline, gcode.name, '[');
+ gcode.name = StripSpaces(gcode.name);
+ gcode.user_defined = true;
+ // read the code creator name
+ std::getline(ssline, gcode.creator, ']');
+ read_state = 1;
+ }
+ break;
+
+ // read code lines
+ case 1:
+ {
+ std::istringstream ssline(line);
+ std::string addr, data;
+ ssline >> addr >> data;
+ ssline.seekg(0);
+
+ // check if this line a code, silly, but the dumb txt file comment lines can start with
+ // valid hex chars :/
+ if (8 == addr.length() && 8 == data.length())
+ {
+ GeckoCode::Code new_code;
+ new_code.original_line = line;
+ ssline >> std::hex >> new_code.address >> new_code.data;
+ gcode.codes.push_back(new_code);
+ }
+ else
+ {
+ gcode.notes.push_back(line);
+ read_state = 2; // start reading comments
+ }
+ }
+ break;
+
+ // read comment lines
+ case 2:
+ // append comment line
+ gcode.notes.push_back(line);
+ break;
+ }
+ }
+
+ // add the last code
+ if (gcode.codes.size())
+ gcodes.push_back(gcode);
+
+ return gcodes;
+}
+
std::vector<GeckoCode> LoadCodes(const IniFile& globalIni, const IniFile& localIni)
{
std::vector<GeckoCode> gcodes;
diff --git a/Source/Core/Core/GeckoCodeConfig.h b/Source/Core/Core/GeckoCodeConfig.h
index 46eb7424c0..88e5b92df5 100644
--- a/Source/Core/Core/GeckoCodeConfig.h
+++ b/Source/Core/Core/GeckoCodeConfig.h
@@ -4,6 +4,7 @@
#pragma once
+#include <string>
#include <vector>
#include "Core/GeckoCode.h"
@@ -12,5 +13,6 @@ class IniFile;
namespace Gecko
{
std::vector<GeckoCode> LoadCodes(const IniFile& globalIni, const IniFile& localIni);
+std::vector<GeckoCode> DownloadCodes(std::string gameid, bool* succeeded);
void SaveCodes(IniFile& inifile, const std::vector<GeckoCode>& gcodes);
}
diff --git a/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp b/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp
index 83733d601b..0228a378f0 100644
--- a/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp
+++ b/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-#include <SFML/Network/Http.hpp>
#include <sstream>
#include <string>
#include <vector>
@@ -160,154 +159,47 @@ void CodeConfigPanel::DownloadCodes(wxCommandEvent&)
if (m_gameid.empty())
return;
- std::string gameid = m_gameid;
-
- switch (m_gameid[0])
+ bool succeeded;
+ std::vector<GeckoCode> gcodes = Gecko::DownloadCodes(m_gameid, &succeeded);
+ if (!succeeded)
{
- case 'R':
- case 'S':
- case 'G':
- break;
- default:
- // All channels (WiiWare, VirtualConsole, etc) are identified by their first four characters
- gameid = m_gameid.substr(0, 4);
- break;
+ WxUtils::ShowErrorDialog(_("Failed to download codes."));
+ return;
}
- sf::Http::Request req;
- req.setUri("/txt.php?txt=" + gameid);
-
- sf::Http http;
- http.setHost("geckocodes.org");
-
- const sf::Http::Response resp = http.sendRequest(req, sf::seconds(5));
-
- if (sf::Http::Response::Ok == resp.getStatus())
+ if (!gcodes.size())
{
- // temp vector containing parsed codes
- std::vector<GeckoCode> gcodes;
-
- // parse the codes
- std::istringstream ss(resp.getBody());
-
- std::string line;
-
- // seek past the header, get to the first code
- std::getline(ss, line);
- std::getline(ss, line);
- std::getline(ss, line);
+ wxMessageBox(_("File contained no codes."));
+ return;
+ }
- int read_state = 0;
- GeckoCode gcode;
+ unsigned long added_count = 0;
- while ((std::getline(ss, line).good()))
+ // append the codes to the code list
+ for (const GeckoCode& code : gcodes)
+ {
+ // only add codes which do not already exist
+ auto existing_gcodes_iter = m_gcodes.begin();
+ auto existing_gcodes_end = m_gcodes.end();
+ for (;; ++existing_gcodes_iter)
{
- // Remove \r at the end of the line for files using windows line endings, std::getline only
- // removes \n
- line = StripSpaces(line);
-
- if (line.empty())
+ if (existing_gcodes_end == existing_gcodes_iter)
{
- // add the code
- if (gcode.codes.size())
- gcodes.push_back(gcode);
- gcode = GeckoCode();
- read_state = 0;
- continue;
- }
-
- switch (read_state)
- {
- // read new code
- case 0:
- {
- std::istringstream ssline(line);
- // stop at [ character (beginning of contributor name)
- std::getline(ssline, gcode.name, '[');
- gcode.name = StripSpaces(gcode.name);
- gcode.user_defined = true;
- // read the code creator name
- std::getline(ssline, gcode.creator, ']');
- read_state = 1;
- }
- break;
-
- // read code lines
- case 1:
- {
- std::istringstream ssline(line);
- std::string addr, data;
- ssline >> addr >> data;
- ssline.seekg(0);
-
- // check if this line a code, silly, but the dumb txt file comment lines can start with
- // valid hex chars :/
- if (8 == addr.length() && 8 == data.length())
- {
- GeckoCode::Code new_code;
- new_code.original_line = line;
- ssline >> std::hex >> new_code.address >> new_code.data;
- gcode.codes.push_back(new_code);
- }
- else
- {
- gcode.notes.push_back(line);
- read_state = 2; // start reading comments
- }
+ m_gcodes.push_back(code);
+ ++added_count;
+ break;
}
- break;
- // read comment lines
- case 2:
- // append comment line
- gcode.notes.push_back(line);
+ // code exists
+ if (*existing_gcodes_iter == code)
break;
- }
}
+ }
- // add the last code
- if (gcode.codes.size())
- gcodes.push_back(gcode);
-
- if (gcodes.size())
- {
- unsigned long added_count = 0;
-
- // append the codes to the code list
- for (const GeckoCode& code : gcodes)
- {
- // only add codes which do not already exist
- auto existing_gcodes_iter = m_gcodes.begin();
- auto existing_gcodes_end = m_gcodes.end();
- for (;; ++existing_gcodes_iter)
- {
- if (existing_gcodes_end == existing_gcodes_iter)
- {
- m_gcodes.push_back(code);
- ++added_count;
- break;
- }
-
- // code exists
- if (*existing_gcodes_iter == code)
- break;
- }
- }
-
- wxMessageBox(wxString::Format(_("Downloaded %lu codes. (added %lu)"),
- (unsigned long)gcodes.size(), added_count));
+ wxMessageBox(wxString::Format(_("Downloaded %lu codes. (added %lu)"),
+ (unsigned long)gcodes.size(), added_count));
- // refresh the list
- UpdateCodeList();
- }
- else
- {
- wxMessageBox(_("File contained no codes."));
- }
- }
- else
- {
- WxUtils::ShowErrorDialog(_("Failed to download codes."));
- }
+ // refresh the list
+ UpdateCodeList();
}
}