upload working but creates duplicates if existing file exists

This commit is contained in:
Chee Yee
2023-02-28 00:49:23 -08:00
parent 837258afda
commit d772b3d3f5
9 changed files with 145 additions and 15 deletions
+1
View File
@@ -129,3 +129,4 @@ STR_PERM_DRIVE_METADATA=View and manage metadata of files in your Google Drive
STR_PERM_DRIVE_METADATA_RO=See information about your Google Drive files
STR_GOOGLE_LOGIN_FAIL_MSG=Google login failed
STR_GOOGLE_LOGIN_TIMEOUT_MSG=Google login timed out
STR_NEW_FILE=New File
+3 -1
View File
@@ -48,7 +48,9 @@ enum ACTIONS
ACTION_REMOTE_CUT,
ACTION_REMOTE_COPY,
ACTION_REMOTE_PASTE,
ACTION_REMOTE_EDIT
ACTION_REMOTE_EDIT,
ACTION_NEW_LOCAL_FILE,
ACTION_NEW_REMOTE_FILE
};
enum OverWriteType
+108 -7
View File
@@ -7,12 +7,16 @@
#include "server/http_server.h"
#include "clients/remote_client.h"
#include "clients/gdrive.h"
#include "fs.h"
#include "lang.h"
#include "util.h"
#include "windows.h"
#include "system.h"
#include "dbglogger.h"
#define GOOGLE_BUF_SIZE 262144
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
using namespace httplib;
std::string GetRedirectUrl()
@@ -42,11 +46,11 @@ int RefreshAccessToken()
client.enable_server_certificate_verification(false);
client.set_follow_location(true);
std::string url = std::string("/token");
std::string post_data = std::string("grant_type=refresh_token") +
"&client_id=" + gg_account.client_id +
"&client_secret=" + gg_account.client_secret +
"&refresh_token=" + gg_account.refresh_token;
std::string post_data = std::string("grant_type=refresh_token") +
"&client_id=" + gg_account.client_id +
"&client_secret=" + gg_account.client_secret +
"&refresh_token=" + gg_account.refresh_token;
if (auto res = client.Post(url, post_data.c_str(), post_data.length(), "application/x-www-form-urlencoded"))
{
if (HTTP_SUCCESS(res->status))
@@ -100,7 +104,7 @@ int GDriveClient::RequestAuthorization()
sceUserServiceGetForegroundUser((int *)&param.userId);
std::string auth_url = std::string(GOOGLE_AUTH_URL "?client_id=") + gg_account.client_id + "&redirect_uri=" + GetRedirectUrl() +
"&response_type=code&access_type=offline&scope=" + GetScopes() + "&include_granted_scopes=true";
"&response_type=code&access_type=offline&scope=" + GetScopes() + "&include_granted_scopes=true";
auth_url = EncodeUrl(auth_url);
std::string launch_uri = std::string("pswebbrowser:search?url=") + auth_url;
int ret = sceShellUIUtilLaunchByUri(launch_uri.c_str(), &param);
@@ -192,6 +196,29 @@ int GDriveClient::Rename(const std::string &src, const std::string &dst)
return 1;
}
bool GDriveClient::FileExists(const std::string &path)
{
std::string id = GetValue(path_id_map, path);
dbglogger_log("path=%s,id=%s", path.c_str(), id.c_str());
if (id.empty()) // then find it parent folder to see if it exists
{
size_t name_separator = path.find_last_of("/");
std::string parent = path.substr(0, name_separator);
dbglogger_log("parent=%s", parent.c_str());
if (FileExists(parent))
{
ListDir(parent);
id = GetValue(path_id_map, path);
dbglogger_log("after listdir path=%s,id=%s", path.c_str(), id.c_str());
if (!id.empty())
return true;
}
}
else
return true;
return false;
}
int GDriveClient::Get(const std::string &outputfile, const std::string &path, uint64_t offset)
{
std::ofstream file_stream(outputfile, std::ios::binary);
@@ -215,7 +242,77 @@ int GDriveClient::Get(const std::string &outputfile, const std::string &path, ui
sprintf(this->response, "%s", httplib::to_string(res.error()).c_str());
}
return 0;
}
int GDriveClient::Put(const std::string &inputfile, const std::string &path, uint64_t offset)
{
bytes_to_download = FS::GetSize(inputfile);
dbglogger_log("bytes_to_download=%ld", bytes_to_download);
bytes_transfered = 0;
std::ifstream file_stream(inputfile, std::ios::binary);
bytes_transfered = 0;
size_t path_pos = path.find_last_of("/");
std::string parent_dir;
if (path_pos == 0)
parent_dir = "/";
else
parent_dir = path.substr(0, path_pos);
std::string filename = path.substr(path_pos + 1);
std::string parent_id = GetValue(path_id_map, parent_dir);
std::string url = "/upload/drive/v3/files?uploadType=resumable";
std::string post_data = std::string("{'name': '") + filename + "', 'parents': ['" + parent_id + "']}";
Headers headers;
headers.insert(std::make_pair("X-Upload-Content-Type", "application/octet-stream"));
headers.insert(std::make_pair("X-Upload-Content-Length", std::to_string(bytes_to_download)));
char *buf = new char[GOOGLE_BUF_SIZE];
if (auto res = client->Post(url, headers, post_data.c_str(), post_data.length(), "application/json"))
{
if (HTTP_SUCCESS(res->status))
{
std::string upload_uri = res->get_header_value("location");
upload_uri = std::regex_replace(upload_uri, std::regex(GOOGLE_API_URL), "");
dbglogger_log("upload_uri=%s", upload_uri.c_str());
Headers headers;
headers.insert(std::make_pair("Content-Length", std::to_string(bytes_to_download)));
std::string range_value = "bytes 0-" + std::to_string(bytes_to_download-1) + "/" + std::to_string(bytes_to_download);
headers.insert(std::make_pair("Content-Range", range_value));
dbglogger_log("range_value=%s", range_value.c_str());
auto res = client->Put(
upload_uri, bytes_to_download,
[&file_stream, &buf](size_t offset, size_t length, DataSink &sink)
{
dbglogger_log("offset=%ld, length=%ld", offset, length);
uint32_t count = 0;
uint32_t bytes_to_transfer = MIN(GOOGLE_BUF_SIZE, length-count);
do
{
file_stream.read(buf, bytes_to_transfer);
sink.write(buf, bytes_to_transfer);
count += bytes_to_transfer;
bytes_transfered += bytes_to_transfer;
bytes_to_transfer = MIN(GOOGLE_BUF_SIZE, length-count);
dbglogger_log("count=%ld, bytes_to_transfer=%ld, bytes_transfered=%d", count, bytes_to_transfer, bytes_transfered);
} while (count < length);
return true;
},
"application/octet-stream");
dbglogger_log("bytes_left=%ld", bytes_to_download-bytes_transfered);
}
else
{
delete[] buf;
file_stream.close();
return 0;
}
}
delete[] buf;
file_stream.close();
return 1;
}
int GDriveClient::Size(const std::string &path, int64_t *size)
@@ -243,6 +340,10 @@ int GDriveClient::Size(const std::string &path, int64_t *size)
int GDriveClient::Mkdir(const std::string &path)
{
// if path already exists return;
if (FileExists(path))
return 1;
size_t path_pos = path.find_last_of("/");
std::string parent_dir;
if (path_pos == 0)
@@ -295,7 +396,7 @@ int GDriveClient::Rmdir(const std::string &path, bool recursive)
if (ret != 0)
{
std::string subfolders = path + "/";
for (std::map<std::string, std::string>::iterator it = path_id_map.begin(); it != path_id_map.end(); )
for (std::map<std::string, std::string>::iterator it = path_id_map.begin(); it != path_id_map.end();)
{
if (strncmp(it->first.c_str(), subfolders.c_str(), path.length()) == 0)
{
+2
View File
@@ -19,10 +19,12 @@ public:
int Connect(const std::string &url, const std::string &user, const std::string &pass);
int Rename(const std::string &src, const std::string &dst);
int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0);
int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0);
int Size(const std::string &path, int64_t *size);
int Mkdir(const std::string &path);
int Rmdir(const std::string &path, bool recursive);
int Delete(const std::string &path);
bool FileExists(const std::string &path);
std::vector<DirEntry> ListDir(const std::string &path);
static void *RefreshTokenThread(void *argp);
static void StartRefreshToken();
+2 -1
View File
@@ -18,7 +18,8 @@ enum RemoteActions
REMOTE_ACTION_UPLOAD = 128,
REMOTE_ACTION_INSTALL = 256,
REMOTE_ACTION_EDIT = 512,
REMOTE_ACTION_ALL = 1023
REMOTE_ACTION_NEW_FILE = 1024,
REMOTE_ACTION_ALL = 2047
};
enum ClientType
+1
View File
@@ -144,6 +144,7 @@ char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE] = {
"See information about your Google Drive files", // STR_PERM_DRIVE_METADATA_RO
"Google login failed", // STR_GOOGLE_LOGIN_FAIL_MSG
"Google login timed out", // STR_GOOGLE_LOGIN_TIMEOUT_MSG
"New File", // STR_NEW_FILE
};
bool needs_extended_font = false;
+3 -2
View File
@@ -135,7 +135,8 @@
FUNC(STR_PERM_DRIVE_METADATA) \
FUNC(STR_PERM_DRIVE_METADATA_RO) \
FUNC(STR_GOOGLE_LOGIN_FAIL_MSG) \
FUNC(STR_GOOGLE_LOGIN_TIMEOUT_MSG)
FUNC(STR_GOOGLE_LOGIN_TIMEOUT_MSG) \
FUNC(STR_NEW_FILE)
#define GET_VALUE(x) x,
#define GET_STRING(x) #x,
@@ -145,7 +146,7 @@ enum
FOREACH_STR(GET_VALUE)
};
#define LANG_STRINGS_NUM 132
#define LANG_STRINGS_NUM 133
#define LANG_ID_SIZE 64
#define LANG_STR_SIZE 384
extern char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE];
+1
View File
@@ -81,6 +81,7 @@ namespace HttpServer
{
sprintf(gg_account.auth_code, "%s", req.get_param_value("code").c_str());
Client client(GOOGLE_OAUTH_HOST);
client.set_follow_location(true);
client.enable_server_certificate_verification(false);
std::string url = std::string("/token");
+24 -4
View File
@@ -795,13 +795,13 @@ namespace Windows
bool remote_browser_selected = saved_selected_browser & REMOTE_BROWSER;
if (local_browser_selected)
{
ImGui::SetNextWindowPos(ImVec2(410, 300));
ImGui::SetNextWindowPos(ImVec2(410, 280));
}
else if (remote_browser_selected)
{
ImGui::SetNextWindowPos(ImVec2(1330, 300));
ImGui::SetNextWindowPos(ImVec2(1330, 280));
}
ImGui::SetNextWindowSizeConstraints(ImVec2(230, 150), ImVec2(230, 600), NULL, NULL);
ImGui::SetNextWindowSizeConstraints(ImVec2(230, 150), ImVec2(230, 625), NULL, NULL);
if (ImGui::BeginPopupModal(lang_strings[STR_ACTIONS], NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::PushID("Select All##settings");
@@ -934,9 +934,28 @@ namespace Windows
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("New File##settings");
flags = ImGuiSelectableFlags_None;
if (remote_browser_selected && remoteclient != nullptr && !(remoteclient->SupportedActions() & REMOTE_ACTION_NEW_FILE))
{
flags = ImGuiSelectableFlags_Disabled;
}
if (ImGui::Selectable(lang_strings[STR_NEW_FILE], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
if (local_browser_selected)
selected_action = ACTION_NEW_LOCAL_FILE;
else if (remote_browser_selected)
selected_action = ACTION_NEW_REMOTE_FILE;
SetModalMode(false);
ImGui::CloseCurrentPopup();
}
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("Edit##settings");
flags = ImGuiSelectableFlags_None;
if (remote_browser_selected && remoteclient != nullptr && !(remoteclient->SupportedActions() & REMOTE_ACTION_EDIT))
if ((remote_browser_selected && remoteclient != nullptr && (!(remoteclient->SupportedActions() & REMOTE_ACTION_EDIT) || selected_remote_file.isDir)) ||
(local_browser_selected && selected_local_file.isDir))
{
flags = ImGuiSelectableFlags_Disabled;
}
@@ -1422,6 +1441,7 @@ namespace Windows
FS::SaveText(&edit_buffer, TMP_EDITOR_FILE);
if (remoteclient != nullptr)
{
remoteclient->Delete(selected_remote_file.path);
remoteclient->Put(TMP_EDITOR_FILE, selected_remote_file.path);
selected_action = ACTION_REFRESH_REMOTE_FILES;
}