mirror of
https://github.com/J-D-K/JKSV.git
synced 2026-03-21 17:24:37 -05:00
Remove cfg::driveAuthCode, login on switch instead
This commit is contained in:
parent
00dd0ee6af
commit
b2be2a26fb
2
Makefile
2
Makefile
|
|
@ -38,7 +38,7 @@ INCLUDES := inc inc/ui inc/fs
|
|||
EXEFS_SRC := exefs_src
|
||||
APP_TITLE := JKSV
|
||||
APP_AUTHOR := JK
|
||||
APP_VERSION := 11.28.2021
|
||||
APP_VERSION := 12.15.2021
|
||||
ROMFS := romfs
|
||||
ICON := icon.jpg
|
||||
|
||||
|
|
|
|||
|
|
@ -34,5 +34,5 @@ namespace cfg
|
|||
extern std::vector<uint64_t> blacklist;
|
||||
extern std::vector<uint64_t> favorites;
|
||||
extern uint8_t sortType;
|
||||
extern std::string driveClientID, driveClientSecret, driveRefreshToken, driveAuthCode;
|
||||
extern std::string driveClientID, driveClientSecret, driveRefreshToken;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
#include "gfx.h"
|
||||
|
||||
#define BLD_MON 11
|
||||
#define BLD_DAY 28
|
||||
#define BLD_MON 12
|
||||
#define BLD_DAY 15
|
||||
#define BLD_YEAR 2021
|
||||
|
||||
namespace data
|
||||
|
|
|
|||
|
|
@ -2,9 +2,14 @@
|
|||
|
||||
#include "../gd.h"
|
||||
|
||||
#define JKSV_DRIVE_FOLDER "JKSV"
|
||||
|
||||
namespace fs
|
||||
{
|
||||
extern drive::gd *gDrive;
|
||||
extern std::string jksvDriveID;
|
||||
|
||||
void driveInit();
|
||||
void driveExit();
|
||||
std::string driveSignInGetAuthCode();
|
||||
}
|
||||
46
inc/gd.h
46
inc/gd.h
|
|
@ -18,38 +18,36 @@ namespace drive
|
|||
{
|
||||
typedef struct
|
||||
{
|
||||
std::string name, id, mimeType;
|
||||
std::string name, id, parent;
|
||||
bool isDir = false;
|
||||
unsigned int size;
|
||||
std::vector<std::string> parents;
|
||||
} gdDirItem;
|
||||
} gdItem;
|
||||
|
||||
class gd
|
||||
{
|
||||
public:
|
||||
gd(const std::string& _clientID, const std::string& _secretID, const std::string& _authCode, const std::string& _rToken);
|
||||
void setClientID(const std::string& _clientID) { clientID = _clientID; }
|
||||
void setClientSecret(const std::string& _clientSecret) { secretID = _clientSecret; }
|
||||
void setRefreshToken(const std::string& _refreshToken) { rToken = _refreshToken; }
|
||||
|
||||
void exhangeAuthCode(const std::string& _authCode);
|
||||
bool exhangeAuthCode(const std::string& _authCode);
|
||||
bool hasToken() { return token.empty() == false; }
|
||||
void refreshToken();
|
||||
bool refreshToken();
|
||||
bool tokenIsValid();
|
||||
//Drive query parameters are appened to the default
|
||||
void loadDriveList(const std::string& _qParams);
|
||||
|
||||
|
||||
void clearDriveList() { driveList.clear(); }
|
||||
void driveListInit(const std::string& _q);
|
||||
void driveListAppend(const std::string& _q);
|
||||
void getListWithParent(const std::string& _parent, std::vector<drive::gdItem *>& _out);
|
||||
void debugWriteList();
|
||||
|
||||
bool createDir(const std::string& _dirName);
|
||||
bool createDir(const std::string& _dirName, const std::string& _parent);
|
||||
bool dirExists(const std::string& _dirName);
|
||||
void setRootDir(const std::string& _dirID)
|
||||
{
|
||||
rootDir = _dirID;
|
||||
parentDir = _dirID;
|
||||
loadDriveList("");
|
||||
}
|
||||
void returnToRoot(){ parentDir = rootDir; loadDriveList(""); }
|
||||
void chDir(const std::string& _dirID) { parentDir = _dirID; loadDriveList(""); }
|
||||
bool dirExists(const std::string& _dirName, const std::string& _parent);
|
||||
|
||||
bool fileExists(const std::string& _filename);
|
||||
void uploadFile(const std::string& _filename, curlFuncs::curlUpArgs *_upload);
|
||||
bool fileExists(const std::string& _filename, const std::string& _parent);
|
||||
void uploadFile(const std::string& _filename, const std::string& _parent, curlFuncs::curlUpArgs *_upload);
|
||||
void updateFile(const std::string& _fileID, curlFuncs::curlUpArgs *_upload);
|
||||
void downloadFile(const std::string& _fileID, curlFuncs::curlDlArgs *_download);
|
||||
void deleteFile(const std::string& _fileID);
|
||||
|
|
@ -57,14 +55,16 @@ namespace drive
|
|||
std::string getClientID() const { return clientID; }
|
||||
std::string getClientSecret() const { return secretID; }
|
||||
std::string getRefreshToken() const { return rToken; }
|
||||
std::string getFileID(const std::string& name);
|
||||
std::string getFileID(const std::string& _name);
|
||||
std::string getFileID(const std::string& _name, const std::string& _parent);
|
||||
std::string getDirID(const std::string& _name);
|
||||
std::string getDirID(const std::string& _name, const std::string& _parent);
|
||||
|
||||
size_t getDriveListCount() const { return driveList.size(); }
|
||||
drive::gdDirItem *getDirItemAt(unsigned int _ind) { return &driveList[_ind]; }
|
||||
drive::gdItem *getItemAt(unsigned int _ind) { return &driveList[_ind]; }
|
||||
|
||||
private:
|
||||
std::vector<gdDirItem> driveList;
|
||||
std::vector<gdItem> driveList;
|
||||
std::string clientID, secretID, token, rToken;
|
||||
std::string rootDir = "", parentDir = "";
|
||||
};
|
||||
}
|
||||
|
|
@ -15,5 +15,5 @@ namespace ui
|
|||
|
||||
//Populate to open menu, refresh for updating after actions
|
||||
void fldPopulateMenu();
|
||||
void fldRefreshMenu(bool _updateDrive);
|
||||
void fldRefreshMenu();
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ std::vector<uint64_t> cfg::blacklist;
|
|||
std::vector<uint64_t> cfg::favorites;
|
||||
static std::unordered_map<uint64_t, std::string> pathDefs;
|
||||
uint8_t cfg::sortType;
|
||||
std::string cfg::driveClientID, cfg::driveClientSecret, cfg::driveRefreshToken, cfg::driveAuthCode;
|
||||
std::string cfg::driveClientID, cfg::driveClientSecret, cfg::driveRefreshToken;
|
||||
|
||||
const char *cfgPath = "sdmc:/config/JKSV/JKSV.cfg", *titleDefPath = "sdmc:/config/JKSV/titleDefs.txt", *workDirLegacy = "sdmc:/switch/jksv_dir.txt";
|
||||
static std::unordered_map<std::string, unsigned> cfgStrings =
|
||||
|
|
@ -417,7 +417,7 @@ void cfg::loadConfig()
|
|||
break;
|
||||
|
||||
case 22:
|
||||
cfg::driveAuthCode = cfgRead.getNextValueStr();
|
||||
//cfg::driveAuthCode = cfgRead.getNextValueStr();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -431,7 +431,7 @@ void fs::createNewBackup(void *a)
|
|||
path += "/";
|
||||
fs::copyDirToDirThreaded("sv:/", path);
|
||||
}
|
||||
ui::fldRefreshMenu(false);
|
||||
ui::fldRefreshMenu();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -537,7 +537,7 @@ void fs::restoreBackup(void *a)
|
|||
}
|
||||
}
|
||||
if(cfg::config["autoBack"])
|
||||
ui::fldRefreshMenu(false);
|
||||
ui::fldRefreshMenu();
|
||||
|
||||
delete restore;
|
||||
t->finished = true;
|
||||
|
|
@ -572,7 +572,7 @@ void fs::deleteBackup(void *a)
|
|||
fs::delfile(*deletePath);
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataBackupDeleted", 0), backupName.c_str());
|
||||
}
|
||||
ui::fldRefreshMenu(false);
|
||||
ui::fldRefreshMenu();
|
||||
delete deletePath;
|
||||
t->finished = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,87 @@
|
|||
#include "fs.h"
|
||||
#include "drive.h"
|
||||
#include "cfg.h"
|
||||
#include "ui.h"
|
||||
|
||||
drive::gd *fs::gDrive = NULL;
|
||||
std::string fs::jksvDriveID;
|
||||
|
||||
void fs::driveInit()
|
||||
{
|
||||
if(!cfg::driveClientID.empty() && !cfg::driveClientSecret.empty())
|
||||
if(cfg::driveClientID.empty() || cfg::driveClientSecret.empty())
|
||||
return;
|
||||
|
||||
bool refreshed = false, exchanged = false;
|
||||
fs::gDrive = new drive::gd;
|
||||
fs::gDrive->setClientID(cfg::driveClientID);
|
||||
fs::gDrive->setClientSecret(cfg::driveClientSecret);
|
||||
if(!cfg::driveRefreshToken.empty())
|
||||
{
|
||||
fs::gDrive = new drive::gd(cfg::driveClientID, cfg::driveClientSecret, cfg::driveAuthCode, cfg::driveRefreshToken);
|
||||
if(!fs::gDrive->hasToken())
|
||||
fs::gDrive->setRefreshToken(cfg::driveRefreshToken);
|
||||
refreshed = fs::gDrive->refreshToken();
|
||||
}
|
||||
|
||||
if(!refreshed)
|
||||
{
|
||||
std::string authCode = driveSignInGetAuthCode();
|
||||
exchanged = fs::gDrive->exhangeAuthCode(authCode);
|
||||
}
|
||||
|
||||
if(fs::gDrive->hasToken())
|
||||
{
|
||||
if(exchanged)
|
||||
{
|
||||
delete fs::gDrive;
|
||||
fs::gDrive = NULL;
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popDriveFailed", 0));
|
||||
cfg::driveRefreshToken = fs::gDrive->getRefreshToken();
|
||||
cfg::saveConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!cfg::driveAuthCode.empty() && fs::gDrive->hasToken())
|
||||
{
|
||||
cfg::driveRefreshToken = fs::gDrive->getRefreshToken();
|
||||
cfg::saveConfig();
|
||||
}
|
||||
|
||||
fs::gDrive->loadDriveList("name = 'JKSV'");
|
||||
fs::gDrive->driveListInit("");
|
||||
|
||||
if(!fs::gDrive->dirExists("JKSV"))
|
||||
fs::gDrive->createDir("JKSV");
|
||||
if(!fs::gDrive->dirExists(JKSV_DRIVE_FOLDER))
|
||||
fs::gDrive->createDir(JKSV_DRIVE_FOLDER, "");
|
||||
|
||||
std::string jksvID = fs::gDrive->getFileID("JKSV");
|
||||
fs::gDrive->setRootDir(jksvID);
|
||||
jksvDriveID = fs::gDrive->getDirID(JKSV_DRIVE_FOLDER);
|
||||
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popDriveStarted", 0));
|
||||
}
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popDriveStarted", 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
delete fs::gDrive;
|
||||
fs::gDrive = NULL;
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popDriveFailed", 0));
|
||||
}
|
||||
}
|
||||
|
||||
void fs::driveExit()
|
||||
{
|
||||
if(fs::gDrive)
|
||||
{
|
||||
//Need to save for config if first run
|
||||
cfg::driveRefreshToken = fs::gDrive->getRefreshToken();
|
||||
delete gDrive;
|
||||
}
|
||||
}
|
||||
|
||||
std::string fs::driveSignInGetAuthCode()
|
||||
{
|
||||
std::string url = "https://accounts.google.com/o/oauth2/v2/auth?client_id=" + cfg::driveClientID + "&redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto&response_type=code&scope=https://www.googleapis.com/auth/drive";
|
||||
std::string replyURL;
|
||||
WebCommonConfig webCfg;
|
||||
WebCommonReply webReply;
|
||||
webPageCreate(&webCfg, url.c_str());
|
||||
webConfigSetCallbackUrl(&webCfg, "https://accounts.google.com/o/oauth2/approval/");
|
||||
webConfigShow(&webCfg, &webReply);
|
||||
|
||||
size_t rLength = 0;
|
||||
char replyURLCstr[0x1000];
|
||||
webReplyGetLastUrl(&webReply, replyURLCstr, 0x1000, &rLength);
|
||||
replyURL.assign(replyURLCstr);
|
||||
|
||||
int unescLength = 0;
|
||||
size_t codeBegin = replyURL.find("approvalCode") + 13, codeEnd = replyURL.find_last_of('#');
|
||||
size_t codeLength = codeEnd - codeBegin;
|
||||
replyURL = replyURL.substr(codeBegin, codeLength);
|
||||
|
||||
char *urlUnesc = curl_easy_unescape(NULL, replyURL.c_str(), replyURL.length(), &unescLength);
|
||||
replyURL = urlUnesc;
|
||||
curl_free(urlUnesc);
|
||||
|
||||
//Finally
|
||||
return replyURL;
|
||||
}
|
||||
325
src/gd.cpp
325
src/gd.cpp
|
|
@ -18,6 +18,7 @@ Still major WIP
|
|||
|
||||
#define DRIVE_UPLOAD_BUFFER_SIZE 0x8000
|
||||
#define DRIVE_DOWNLOAD_BUFFER_SIZE 0xA00000
|
||||
#define DRIVE_DEFAULT_PARAMS_AND_QUERY "?fields=files(name,id,mimeType,size,parents)&pageSize=1000&q=trashed=false\%20and\%20\%27me\%27\%20in\%20owners"
|
||||
|
||||
#define tokenURL "https://oauth2.googleapis.com/token"
|
||||
#define tokenCheckURL "https://oauth2.googleapis.com/tokeninfo"
|
||||
|
|
@ -95,22 +96,10 @@ static size_t writeDataBufferThreaded(uint8_t *buff, size_t sz, size_t cnt, void
|
|||
return sz * cnt;
|
||||
}
|
||||
|
||||
drive::gd::gd(const std::string &_clientID, const std::string& _secretID, const std::string& _authCode, const std::string& _rToken)
|
||||
bool drive::gd::exhangeAuthCode(const std::string& _authCode)
|
||||
{
|
||||
clientID = _clientID;
|
||||
secretID = _secretID;
|
||||
rToken = _rToken;
|
||||
bool ret = false;
|
||||
|
||||
if(!_authCode.empty())
|
||||
exhangeAuthCode(_authCode);
|
||||
else if(!rToken.empty())
|
||||
refreshToken();
|
||||
else
|
||||
writeDriveError("gd::gd", "Missing data needed to init Google Drive.\n");
|
||||
}
|
||||
|
||||
void drive::gd::exhangeAuthCode(const std::string& _authCode)
|
||||
{
|
||||
// Header
|
||||
curl_slist *postHeader = NULL;
|
||||
postHeader = curl_slist_append(postHeader, HEADER_CONTENT_TYPE_APP_JSON);
|
||||
|
|
@ -120,7 +109,7 @@ void drive::gd::exhangeAuthCode(const std::string& _authCode)
|
|||
json_object *clientIDString = json_object_new_string(clientID.c_str());
|
||||
json_object *secretIDString = json_object_new_string(secretID.c_str());
|
||||
json_object *authCodeString = json_object_new_string(_authCode.c_str());
|
||||
json_object *redirectUriString = json_object_new_string("urn:ietf:wg:oauth:2.0:oob");
|
||||
json_object *redirectUriString = json_object_new_string("urn:ietf:wg:oauth:2.0:oob:auto");
|
||||
json_object *grantTypeString = json_object_new_string("authorization_code");
|
||||
json_object_object_add(post, "client_id", clientIDString);
|
||||
json_object_object_add(post, "client_secret", secretIDString);
|
||||
|
|
@ -151,9 +140,10 @@ void drive::gd::exhangeAuthCode(const std::string& _authCode)
|
|||
{
|
||||
token = json_object_get_string(accessToken);
|
||||
rToken = json_object_get_string(refreshToken);
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
writeDriveError("exchangeAuthCode", "Error exchanging code for token.");
|
||||
writeDriveError("exchangeAuthCode", jsonResp->c_str());
|
||||
}
|
||||
else
|
||||
writeCurlError("exchangeAuthCode", error);
|
||||
|
|
@ -163,10 +153,14 @@ void drive::gd::exhangeAuthCode(const std::string& _authCode)
|
|||
json_object_put(respParse);
|
||||
curl_slist_free_all(postHeader);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void drive::gd::refreshToken()
|
||||
bool drive::gd::refreshToken()
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
// Header
|
||||
curl_slist *header = NULL;
|
||||
header = curl_slist_append(header, HEADER_CONTENT_TYPE_APP_JSON);
|
||||
|
|
@ -202,9 +196,12 @@ void drive::gd::refreshToken()
|
|||
json_object_object_get_ex(parse, "error", &error);
|
||||
|
||||
if(accessToken)
|
||||
{
|
||||
token = json_object_get_string(accessToken);
|
||||
ret = true;
|
||||
}
|
||||
else if(error)
|
||||
writeDriveError("refreshToken", json_object_get_string(error));
|
||||
writeDriveError("refreshToken", jsonResp->c_str());
|
||||
}
|
||||
|
||||
delete jsonResp;
|
||||
|
|
@ -212,6 +209,8 @@ void drive::gd::refreshToken()
|
|||
json_object_put(parse);
|
||||
curl_slist_free_all(header);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool drive::gd::tokenIsValid()
|
||||
|
|
@ -245,105 +244,139 @@ bool drive::gd::tokenIsValid()
|
|||
return ret;
|
||||
}
|
||||
|
||||
void drive::gd::loadDriveList(const std::string& _qParams)
|
||||
static int requestList(const std::string& _url, const std::string& _token, std::string *_respOut)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
// Headers needed
|
||||
curl_slist *postHeaders = NULL;
|
||||
postHeaders = curl_slist_append(postHeaders, std::string(HEADER_AUTHORIZATION + _token).c_str());
|
||||
|
||||
CURL *curl = curl_easy_init();
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, postHeaders);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, _url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlFuncs::writeDataString);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, _respOut);
|
||||
ret = curl_easy_perform(curl);
|
||||
|
||||
|
||||
curl_slist_free_all(postHeaders);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void processList(const std::string& _json, std::vector<drive::gdItem>& _drvl, bool _clear)
|
||||
{
|
||||
if(_clear)
|
||||
_drvl.clear();
|
||||
|
||||
json_object *parse = json_tokener_parse(_json.c_str()), *fileArray;
|
||||
json_object_object_get_ex(parse, "files", &fileArray);
|
||||
if(fileArray)
|
||||
{
|
||||
size_t arrayLength = json_object_array_length(fileArray);
|
||||
_drvl.reserve(_drvl.size() + arrayLength);
|
||||
for(unsigned i = 0; i < arrayLength; i++)
|
||||
{
|
||||
json_object *idString, *nameString, *mimeTypeString, *size, *parentArray;
|
||||
json_object *curFile = json_object_array_get_idx(fileArray, i);
|
||||
json_object_object_get_ex(curFile, "id", &idString);
|
||||
json_object_object_get_ex(curFile, "name", &nameString);
|
||||
json_object_object_get_ex(curFile, "mimeType", &mimeTypeString);
|
||||
json_object_object_get_ex(curFile, "size", &size);
|
||||
json_object_object_get_ex(curFile, "parents", &parentArray);
|
||||
|
||||
drive::gdItem newDirItem;
|
||||
newDirItem.name = json_object_get_string(nameString);
|
||||
newDirItem.id = json_object_get_string(idString);
|
||||
newDirItem.size = json_object_get_int(size);
|
||||
if(strcmp(json_object_get_string(mimeTypeString), MIMETYPE_FOLDER) == 0)
|
||||
newDirItem.isDir = true;
|
||||
|
||||
if (parentArray)
|
||||
{
|
||||
size_t parentCount = json_object_array_length(parentArray);
|
||||
//There can only be 1 parent, but it's held in an array...
|
||||
for (unsigned j = 0; j < parentCount; j++)
|
||||
{
|
||||
json_object *parent = json_object_array_get_idx(parentArray, j);
|
||||
newDirItem.parent = json_object_get_string(parent);
|
||||
}
|
||||
}
|
||||
_drvl.push_back(newDirItem);
|
||||
}
|
||||
}
|
||||
json_object_put(parse);
|
||||
}
|
||||
|
||||
void drive::gd::driveListInit(const std::string& _q)
|
||||
{
|
||||
if(!tokenIsValid())
|
||||
refreshToken();
|
||||
|
||||
// Request url with specific fields needed.
|
||||
std::string url = driveURL, queryParams = "trashed=false and 'me' in owners ";
|
||||
//These are always used
|
||||
url.append("?fields=files(name,id,mimeType,size,parents)&q=");
|
||||
if(!parentDir.empty())
|
||||
queryParams.append("and '" + parentDir + "' in parents ");
|
||||
if(!_qParams.empty())
|
||||
queryParams.append("and " + _qParams);
|
||||
|
||||
// Headers needed
|
||||
curl_slist *postHeaders = NULL;
|
||||
postHeaders = curl_slist_append(postHeaders, std::string(HEADER_AUTHORIZATION + token).c_str());
|
||||
|
||||
// Curl request
|
||||
std::string *jsonResp = new std::string;
|
||||
CURL *curl = curl_easy_init();
|
||||
|
||||
//I don't understand why this needs a CURL handle...
|
||||
char *urlAppend = curl_easy_escape(curl, queryParams.c_str(), queryParams.length());
|
||||
url.append(urlAppend);
|
||||
curl_free(urlAppend);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, postHeaders);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlFuncs::writeDataString);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, jsonResp);
|
||||
|
||||
int error = curl_easy_perform(curl);
|
||||
|
||||
json_object *parse = json_tokener_parse(jsonResp->c_str());
|
||||
if (error == CURLE_OK)
|
||||
std::string url = std::string(driveURL) + std::string(DRIVE_DEFAULT_PARAMS_AND_QUERY);
|
||||
if(!_q.empty())
|
||||
{
|
||||
driveList.clear();
|
||||
json_object *fileArray;
|
||||
json_object_object_get_ex(parse, "files", &fileArray);
|
||||
if(fileArray)
|
||||
{
|
||||
size_t count = json_object_array_length(fileArray);
|
||||
driveList.reserve(count);
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
json_object *idString, *nameString, *mimeTypeString, *size, *parentArray;
|
||||
json_object *curFile = json_object_array_get_idx(fileArray, i);
|
||||
json_object_object_get_ex(curFile, "id", &idString);
|
||||
json_object_object_get_ex(curFile, "name", &nameString);
|
||||
json_object_object_get_ex(curFile, "mimeType", &mimeTypeString);
|
||||
json_object_object_get_ex(curFile, "size", &size);
|
||||
json_object_object_get_ex(curFile, "parents", &parentArray);
|
||||
|
||||
drive::gdDirItem newDirItem;
|
||||
newDirItem.name = json_object_get_string(nameString);
|
||||
newDirItem.id = json_object_get_string(idString);
|
||||
newDirItem.mimeType = json_object_get_string(mimeTypeString);
|
||||
newDirItem.size = json_object_get_int(size);
|
||||
|
||||
if (parentArray)
|
||||
{
|
||||
size_t parentCount = json_object_array_length(parentArray);
|
||||
for (unsigned j = 0; j < parentCount; j++)
|
||||
{
|
||||
json_object *parent = json_object_array_get_idx(parentArray, j);
|
||||
newDirItem.parents.push_back(json_object_get_string(parent));
|
||||
}
|
||||
}
|
||||
driveList.push_back(newDirItem);
|
||||
}
|
||||
}
|
||||
else
|
||||
writeDriveError("updateList", "Error obtaining drive listing.");
|
||||
char *qEsc = curl_easy_escape(NULL, _q.c_str(), _q.length());
|
||||
url.append(std::string("\%20and\%20") + std::string(qEsc));
|
||||
curl_free(qEsc);
|
||||
}
|
||||
|
||||
std::string jsonResp;
|
||||
int error = requestList(url, token, &jsonResp);
|
||||
if(error == CURLE_OK)
|
||||
processList(jsonResp, driveList, true);
|
||||
else
|
||||
writeCurlError("updateList", error);
|
||||
writeCurlError("driveListInit", error);
|
||||
}
|
||||
|
||||
delete jsonResp;
|
||||
json_object_put(parse);
|
||||
curl_slist_free_all(postHeaders);
|
||||
curl_easy_cleanup(curl);
|
||||
void drive::gd::driveListAppend(const std::string& _q)
|
||||
{
|
||||
if(!tokenIsValid())
|
||||
refreshToken();
|
||||
|
||||
std::string url = std::string(driveURL) + std::string(DRIVE_DEFAULT_PARAMS_AND_QUERY);
|
||||
if(!_q.empty())
|
||||
{
|
||||
char *qEsc = curl_easy_escape(NULL, _q.c_str(), _q.length());
|
||||
url.append(std::string("\%20and\%20") + std::string(qEsc));
|
||||
curl_free(qEsc);
|
||||
}
|
||||
|
||||
std::string jsonResp;
|
||||
int error = requestList(url, token, &jsonResp);
|
||||
if(error == CURLE_OK)
|
||||
processList(jsonResp, driveList, false);
|
||||
else
|
||||
writeCurlError("driveListAppend", error);
|
||||
}
|
||||
|
||||
void drive::gd::getListWithParent(const std::string& _parent, std::vector<drive::gdItem *>& _out)
|
||||
{
|
||||
_out.clear();
|
||||
for(unsigned i = 0; i < driveList.size(); i++)
|
||||
{
|
||||
if(driveList[i].parent == _parent)
|
||||
_out.push_back(&driveList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void drive::gd::debugWriteList()
|
||||
{
|
||||
fs::logWrite("Parent: %s\n", parentDir.c_str());
|
||||
for(auto& di : driveList)
|
||||
{
|
||||
fs::logWrite("%s\n\t%s\n", di.name.c_str(), di.id.c_str());
|
||||
if(!di.parents.empty())
|
||||
fs::logWrite("\t%s\n", di.parents[0].c_str());
|
||||
if(!di.parent.empty())
|
||||
fs::logWrite("\t%s\n", di.parent.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool drive::gd::createDir(const std::string& _dirName)
|
||||
bool drive::gd::createDir(const std::string& _dirName, const std::string& _parent)
|
||||
{
|
||||
if(!tokenIsValid())
|
||||
refreshToken();
|
||||
|
|
@ -361,10 +394,10 @@ bool drive::gd::createDir(const std::string& _dirName)
|
|||
json_object *mimeTypeString = json_object_new_string(MIMETYPE_FOLDER);
|
||||
json_object_object_add(post, "name", nameString);
|
||||
json_object_object_add(post, "mimeType", mimeTypeString);
|
||||
if (!parentDir.empty())
|
||||
if (!_parent.empty())
|
||||
{
|
||||
json_object *parentsArray = json_object_new_array();
|
||||
json_object *parentString = json_object_new_string(parentDir.c_str());
|
||||
json_object *parentString = json_object_new_string(_parent.c_str());
|
||||
json_object_array_add(parentsArray, parentString);
|
||||
json_object_object_add(post, "parents", parentsArray);
|
||||
}
|
||||
|
|
@ -389,11 +422,12 @@ bool drive::gd::createDir(const std::string& _dirName)
|
|||
json_object *id;
|
||||
json_object_object_get_ex(respParse, "id", &id);
|
||||
|
||||
drive::gdDirItem newDir;
|
||||
drive::gdItem newDir;
|
||||
newDir.name = _dirName;
|
||||
newDir.id = json_object_get_string(id);
|
||||
newDir.mimeType = MIMETYPE_FOLDER;
|
||||
newDir.isDir = true;
|
||||
newDir.size = 0;
|
||||
newDir.parent = _parent;
|
||||
driveList.push_back(newDir);
|
||||
}
|
||||
else
|
||||
|
|
@ -409,37 +443,45 @@ bool drive::gd::createDir(const std::string& _dirName)
|
|||
|
||||
bool drive::gd::dirExists(const std::string& _dirName)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
for(unsigned i = 0; i < driveList.size(); i++)
|
||||
{
|
||||
if(driveList[i].name == _dirName && driveList[i].mimeType == MIMETYPE_FOLDER)
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
if(driveList[i].isDir && driveList[i].name == _dirName)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
bool drive::gd::dirExists(const std::string& _dirName, const std::string& _parent)
|
||||
{
|
||||
for(unsigned i = 0; i < driveList.size(); i++)
|
||||
{
|
||||
if(driveList[i].isDir && driveList[i].name == _dirName && driveList[i].parent == _parent)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool drive::gd::fileExists(const std::string& _filename)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
for(unsigned i = 0; i < driveList.size(); i++)
|
||||
{
|
||||
if(driveList[i].name == _filename && driveList[i].mimeType != MIMETYPE_FOLDER)
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
if(!driveList[i].isDir && driveList[i].name == _filename)
|
||||
return true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
void drive::gd::uploadFile(const std::string& _filename, curlFuncs::curlUpArgs *_upload)
|
||||
bool drive::gd::fileExists(const std::string& _filename, const std::string& _parent)
|
||||
{
|
||||
for(unsigned i = 0; i < driveList.size(); i++)
|
||||
{
|
||||
if(!driveList[i].isDir && driveList[i].name == _filename && driveList[i].parent == _parent)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void drive::gd::uploadFile(const std::string& _filename, const std::string& _parent, curlFuncs::curlUpArgs *_upload)
|
||||
{
|
||||
if(!tokenIsValid())
|
||||
refreshToken();
|
||||
|
|
@ -456,10 +498,10 @@ void drive::gd::uploadFile(const std::string& _filename, curlFuncs::curlUpArgs *
|
|||
json_object *post = json_object_new_object();
|
||||
json_object *nameString = json_object_new_string(_filename.c_str());
|
||||
json_object_object_add(post, "name", nameString);
|
||||
if (!parentDir.empty())
|
||||
if (!_parent.empty())
|
||||
{
|
||||
json_object *parentArray = json_object_new_array();
|
||||
json_object *parentString = json_object_new_string(parentDir.c_str());
|
||||
json_object *parentString = json_object_new_string(_parent.c_str());
|
||||
json_object_array_add(parentArray, parentString);
|
||||
json_object_object_add(post, "parents", parentArray);
|
||||
}
|
||||
|
|
@ -499,14 +541,15 @@ void drive::gd::uploadFile(const std::string& _filename, curlFuncs::curlUpArgs *
|
|||
|
||||
if(name && id && mimeType)
|
||||
{
|
||||
drive::gdDirItem uploadData;
|
||||
drive::gdItem uploadData;
|
||||
uploadData.id = json_object_get_string(id);
|
||||
uploadData.name = json_object_get_string(name);
|
||||
uploadData.mimeType = json_object_get_string(mimeType);
|
||||
uploadData.isDir = false;
|
||||
uploadData.size = *_upload->o;//should be safe to use
|
||||
uploadData.parents.push_back(parentDir);
|
||||
uploadData.parent = _parent;
|
||||
driveList.push_back(uploadData);
|
||||
}
|
||||
json_object_put(parse);
|
||||
}
|
||||
else
|
||||
writeCurlError("uploadFile", error);
|
||||
|
|
@ -633,7 +676,37 @@ std::string drive::gd::getFileID(const std::string& _name)
|
|||
{
|
||||
for(unsigned i = 0; i < driveList.size(); i++)
|
||||
{
|
||||
if(driveList[i].name == _name)
|
||||
if(!driveList[i].isDir && driveList[i].name == _name)
|
||||
return driveList[i].id;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string drive::gd::getFileID(const std::string& _name, const std::string& _parent)
|
||||
{
|
||||
for(unsigned i = 0; i < driveList.size(); i++)
|
||||
{
|
||||
if(!driveList[i].isDir && driveList[i].name == _name && driveList[i].parent == _parent)
|
||||
return driveList[i].id;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string drive::gd::getDirID(const std::string& _name)
|
||||
{
|
||||
for(unsigned i = 0; i < driveList.size(); i++)
|
||||
{
|
||||
if(driveList[i].isDir && driveList[i].name == _name)
|
||||
return driveList[i].id;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string drive::gd::getDirID(const std::string& _name, const std::string& _parent)
|
||||
{
|
||||
for(unsigned i = 0; i < driveList.size(); i++)
|
||||
{
|
||||
if(driveList[i].isDir && driveList[i].name == _name && driveList[i].parent == _parent)
|
||||
return driveList[i].id;
|
||||
}
|
||||
return "";
|
||||
|
|
|
|||
|
|
@ -11,15 +11,14 @@ static fs::dirList *fldList = NULL;
|
|||
static SDL_Texture *fldBuffer;
|
||||
static unsigned int fldGuideWidth = 0;
|
||||
static Mutex fldLock = 0;
|
||||
static std::string driveParent;
|
||||
static std::vector<drive::gdItem *> driveFldList;
|
||||
|
||||
static void fldMenuCallback(void *a)
|
||||
{
|
||||
switch(ui::padKeysDown())
|
||||
{
|
||||
case HidNpadButton_B:
|
||||
if(fs::gDrive)
|
||||
fs::gDrive->returnToRoot();
|
||||
|
||||
fs::unmountSave();
|
||||
fs::freePathFilters();
|
||||
fldMenu->setActive(false);
|
||||
|
|
@ -134,7 +133,7 @@ static void fldFuncUpload_t(void *a)
|
|||
fs::gDrive->updateFile(id, &upload);
|
||||
}
|
||||
else
|
||||
fs::gDrive->uploadFile(filename, &upload);
|
||||
fs::gDrive->uploadFile(filename, driveParent, &upload);
|
||||
|
||||
fclose(upload.f);
|
||||
|
||||
|
|
@ -147,7 +146,7 @@ static void fldFuncUpload_t(void *a)
|
|||
if(cfg::config["ovrClk"])
|
||||
util::sysNormal();
|
||||
|
||||
ui::fldRefreshMenu(false);
|
||||
ui::fldRefreshMenu();
|
||||
|
||||
t->finished = true;
|
||||
}
|
||||
|
|
@ -163,7 +162,7 @@ static void fldFuncUpload(void *a)
|
|||
static void fldFuncDownload_t(void *a)
|
||||
{
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
drive::gdDirItem *in = (drive::gdDirItem *)t->argPtr;
|
||||
drive::gdItem *in = (drive::gdItem *)t->argPtr;
|
||||
data::userTitleInfo *utinfo = data::getCurrentUserTitleInfo();
|
||||
data::titleInfo *tinfo = data::getTitleInfoByTID(utinfo->tid);
|
||||
std::string targetPath = util::generatePathByTID(utinfo->tid) + in->name;
|
||||
|
|
@ -198,14 +197,14 @@ static void fldFuncDownload_t(void *a)
|
|||
if(cfg::config["ovrClk"])
|
||||
util::sysNormal();
|
||||
|
||||
ui::fldRefreshMenu(false);
|
||||
ui::fldRefreshMenu();
|
||||
|
||||
t->finished = true;
|
||||
}
|
||||
|
||||
static void fldFuncDownload(void *a)
|
||||
{
|
||||
drive::gdDirItem *in = (drive::gdDirItem *)a;
|
||||
drive::gdItem *in = (drive::gdItem *)a;
|
||||
data::userTitleInfo *utinfo = data::getCurrentUserTitleInfo();
|
||||
data::titleInfo *tinfo = data::getTitleInfoByTID(utinfo->tid);
|
||||
std::string testPath = util::generatePathByTID(utinfo->tid) + in->name;
|
||||
|
|
@ -222,25 +221,24 @@ static void fldFuncDownload(void *a)
|
|||
static void fldFuncDriveDelete_t(void *a)
|
||||
{
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
drive::gdDirItem *gdi = (drive::gdDirItem *)t->argPtr;
|
||||
drive::gdItem *gdi = (drive::gdItem *)t->argPtr;
|
||||
t->status->setStatus(ui::getUICString("threadStatusDeletingFile", 0));
|
||||
fs::gDrive->deleteFile(gdi->id);
|
||||
ui::fldRefreshMenu(true);
|
||||
ui::fldRefreshMenu();
|
||||
t->finished = true;
|
||||
}
|
||||
|
||||
static void fldFuncDriveDelete(void *a)
|
||||
{
|
||||
drive::gdDirItem *in = (drive::gdDirItem *)a;
|
||||
drive::gdItem *in = (drive::gdItem *)a;
|
||||
ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdDel"], fldFuncDriveDelete_t, NULL, a, ui::getUICString("confirmDelete", 0), in->name.c_str());
|
||||
ui::confirm(conf);
|
||||
}
|
||||
|
||||
//TODO
|
||||
static void fldFuncDriveRestore_t(void *a)
|
||||
{
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
drive::gdDirItem *gdi = (drive::gdDirItem *)t->argPtr;
|
||||
drive::gdItem *gdi = (drive::gdItem *)t->argPtr;
|
||||
t->status->setStatus(ui::getUICString("threadStatusDownloadingFile", 0), gdi->name.c_str());
|
||||
|
||||
fs::copyArgs *cpy = fs::copyArgsCreate("", "", "", NULL, NULL, false, false, 0);
|
||||
|
|
@ -270,7 +268,7 @@ static void fldFuncDriveRestore_t(void *a)
|
|||
|
||||
static void fldFuncDriveRestore(void *a)
|
||||
{
|
||||
drive::gdDirItem *in = (drive::gdDirItem *)a;
|
||||
drive::gdItem *in = (drive::gdItem *)a;
|
||||
ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdOver"], fldFuncDriveRestore_t, NULL, a, ui::getUICString("confirmRestore", 0), in->name.c_str());
|
||||
ui::confirm(conf);
|
||||
}
|
||||
|
|
@ -315,31 +313,27 @@ void ui::fldPopulateMenu()
|
|||
std::string targetDir = util::generatePathByTID(d->tid);
|
||||
|
||||
fldList->reassign(targetDir);
|
||||
if(fs::gDrive)
|
||||
{
|
||||
if(!fs::gDrive->dirExists(t->title))
|
||||
fs::gDrive->createDir(t->title);
|
||||
|
||||
std::string dirID = fs::gDrive->getFileID(t->title);
|
||||
fs::gDrive->chDir(dirID);
|
||||
}
|
||||
|
||||
fs::loadPathFilters(d->tid);
|
||||
|
||||
fldMenu->addOpt(NULL, ui::getUICString("folderMenuNew", 0));
|
||||
fldMenu->optAddButtonEvent(0, HidNpadButton_A, fs::createNewBackup, NULL);
|
||||
|
||||
unsigned fldInd = 1;
|
||||
if(fs::gDrive && fs::gDrive->getDriveListCount() > 0)
|
||||
if(fs::gDrive)
|
||||
{
|
||||
for(unsigned i = 0; i < fs::gDrive->getDriveListCount(); i++, fldInd++)
|
||||
{
|
||||
drive::gdDirItem *gdi = fs::gDrive->getDirItemAt(i);
|
||||
fldMenu->addOpt(NULL, "[GD] " + gdi->name);
|
||||
if(!fs::gDrive->dirExists(t->title, fs::jksvDriveID))
|
||||
fs::gDrive->createDir(t->title, fs::jksvDriveID);
|
||||
|
||||
fldMenu->optAddButtonEvent(fldInd, HidNpadButton_A, fldFuncDownload, gdi);
|
||||
fldMenu->optAddButtonEvent(fldInd, HidNpadButton_X, fldFuncDriveDelete, gdi);
|
||||
fldMenu->optAddButtonEvent(fldInd, HidNpadButton_Y, fldFuncDriveRestore, gdi);
|
||||
driveParent = fs::gDrive->getDirID(t->title, fs::jksvDriveID);
|
||||
|
||||
fs::gDrive->getListWithParent(driveParent, driveFldList);
|
||||
for(unsigned i = 0; i < driveFldList.size(); i++, fldInd++)
|
||||
{
|
||||
fldMenu->addOpt(NULL, "[GD] " + driveFldList[i]->name);
|
||||
|
||||
fldMenu->optAddButtonEvent(fldInd, HidNpadButton_A, fldFuncDownload, driveFldList[i]);
|
||||
fldMenu->optAddButtonEvent(fldInd, HidNpadButton_X, fldFuncDriveDelete, driveFldList[i]);
|
||||
fldMenu->optAddButtonEvent(fldInd, HidNpadButton_Y, fldFuncDriveRestore, driveFldList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -359,7 +353,7 @@ void ui::fldPopulateMenu()
|
|||
mutexUnlock(&fldLock);
|
||||
}
|
||||
|
||||
void ui::fldRefreshMenu(bool _updateDrive)
|
||||
void ui::fldRefreshMenu()
|
||||
{
|
||||
mutexLock(&fldLock);
|
||||
|
||||
|
|
@ -369,23 +363,21 @@ void ui::fldRefreshMenu(bool _updateDrive)
|
|||
std::string targetDir = util::generatePathByTID(utinfo->tid);
|
||||
|
||||
fldList->reassign(targetDir);
|
||||
if(_updateDrive && fs::gDrive)
|
||||
fs::gDrive->loadDriveList("");
|
||||
|
||||
fldMenu->addOpt(NULL, ui::getUIString("folderMenuNew", 0));
|
||||
fldMenu->optAddButtonEvent(0, HidNpadButton_A, fs::createNewBackup, NULL);
|
||||
|
||||
unsigned fldInd = 1;
|
||||
if(fs::gDrive && fs::gDrive->getDriveListCount() > 0)
|
||||
if(fs::gDrive)
|
||||
{
|
||||
for(unsigned i = 0; i < fs::gDrive->getDriveListCount(); i++, fldInd++)
|
||||
{
|
||||
drive::gdDirItem *gdi = fs::gDrive->getDirItemAt(i);
|
||||
fldMenu->addOpt(NULL, "[GD] " + gdi->name);
|
||||
fs::gDrive->getListWithParent(driveParent, driveFldList);
|
||||
|
||||
fldMenu->optAddButtonEvent(fldInd, HidNpadButton_A, fldFuncDownload, gdi);
|
||||
fldMenu->optAddButtonEvent(fldInd, HidNpadButton_X, fldFuncDriveDelete, gdi);
|
||||
fldMenu->optAddButtonEvent(fldInd, HidNpadButton_Y, fldFuncDriveRestore, gdi);
|
||||
for(unsigned i = 0; i < driveFldList.size(); i++, fldInd++)
|
||||
{
|
||||
fldMenu->addOpt(NULL, "[GD] " + driveFldList[i]->name);
|
||||
|
||||
fldMenu->optAddButtonEvent(fldInd, HidNpadButton_A, fldFuncDownload, driveFldList[i]);
|
||||
fldMenu->optAddButtonEvent(fldInd, HidNpadButton_X, fldFuncDriveDelete, driveFldList[i]);
|
||||
fldMenu->optAddButtonEvent(fldInd, HidNpadButton_Y, fldFuncDriveRestore, driveFldList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user