Remove cfg::driveAuthCode, login on switch instead

This commit is contained in:
J-D-K 2021-12-15 20:04:47 -05:00
parent 00dd0ee6af
commit b2be2a26fb
11 changed files with 336 additions and 226 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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 = "";
};
}

View File

@ -15,5 +15,5 @@ namespace ui
//Populate to open menu, refresh for updating after actions
void fldPopulateMenu();
void fldRefreshMenu(bool _updateDrive);
void fldRefreshMenu();
}

View File

@ -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:

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 "";

View File

@ -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]);
}
}