diff --git a/source/clients/baseclient.cpp b/source/clients/baseclient.cpp index 6eddce8..e17483c 100644 --- a/source/clients/baseclient.cpp +++ b/source/clients/baseclient.cpp @@ -94,6 +94,35 @@ int BaseClient::Get(const std::string &outputfile, const std::string &path, uint return 0; } +int BaseClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset) +{ + char range_header[64]; + sprintf(range_header, "bytes=%lu-%lu", offset, offset+size-1); + Headers headers = {{"Range", range_header}}; + size_t bytes_read = 0; + std::vector body; + if (auto res = client->Get(GetFullPath(path), headers, + [&](const char *data, size_t data_length) + { + body.insert(body.end(), data, data + data_length); + bytes_read += data_length; + if (bytes_read > size) + return false; + return true; + })) + { + if (body.size() != size) + return 0; + memcpy(buffer, body.data(), size); + return 1; + } + else + { + sprintf(this->response, "%s", httplib::to_string(res.error()).c_str()); + } + return 0; +} + int BaseClient::Put(const std::string &inputfile, const std::string &path, uint64_t offset) { sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]); diff --git a/source/clients/baseclient.h b/source/clients/baseclient.h index 9ac5a65..7565b50 100644 --- a/source/clients/baseclient.h +++ b/source/clients/baseclient.h @@ -17,6 +17,7 @@ public: int Rmdir(const std::string &path, bool recursive); int Size(const std::string &path, int64_t *size); int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0); + int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset); int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0); int Rename(const std::string &src, const std::string &dst); int Delete(const std::string &path); diff --git a/source/clients/ftpclient.cpp b/source/clients/ftpclient.cpp index c4bcda3..90ed189 100644 --- a/source/clients/ftpclient.cpp +++ b/source/clients/ftpclient.cpp @@ -16,7 +16,6 @@ #include "util.h" #include "windows.h" - #define FTP_CLIENT_BUFSIZ 1048576 #define ACCEPT_TIMEOUT 30 @@ -1267,6 +1266,40 @@ int FtpClient::Get(const std::string &outputfile, const std::string &path, uint6 return FtpXfer(outputfile, path, mp_ftphandle, FtpClient::filereadappend, FtpClient::transfermode::image); } +int FtpClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset) +{ + ftphandle *nData; + mp_ftphandle->offset = offset; + if (!FtpAccess(path, FtpClient::fileread, FtpClient::transfermode::image, mp_ftphandle, &nData)) + { + return 0; + } + + char buf[8192]; + int l = 0; + uint64_t remaining = size; + char *p = (char*) buffer; + while ((l = FtpRead(buf, 8192, nData)) > 0) + { + if (l <= remaining) + { + memcpy(p, buf, l); + p += l; + } + else + { + memcpy(p, buf, remaining); + break; + } + remaining -= l; + } + FtpClose(nData); + mp_ftphandle->offset = 0; + + return 1; + +} + /* * FtpPut - issue a PUT command and send data from input * diff --git a/source/clients/ftpclient.h b/source/clients/ftpclient.h index 0bfe11f..c784124 100644 --- a/source/clients/ftpclient.h +++ b/source/clients/ftpclient.h @@ -78,6 +78,7 @@ public: int Rmdir(const std::string &path, bool recursive); int Size(const std::string &path, int64_t *size); int Get(const std::string &outputfile, const std::string &path, uint64_t offset = 0); + int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset); int Put(const std::string &inputfile, const std::string &path, uint64_t offset = 0); int Rename(const std::string &src, const std::string &dst); int Delete(const std::string &path); diff --git a/source/clients/gdrive.cpp b/source/clients/gdrive.cpp index 60c8de4..3eadac2 100644 --- a/source/clients/gdrive.cpp +++ b/source/clients/gdrive.cpp @@ -331,6 +331,41 @@ int GDriveClient::Get(const std::string &outputfile, const std::string &path, ui return 0; } +int GDriveClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset) +{ + size_t bytes_read = 0; + std::vector body; + std::string id = GetValue(path_id_map, path); + std::string drive_id = GetDriveId(path); + + std::string url = std::string("/drive/v3/files/") + BaseClient::EncodeUrl(id) + "?alt=media"; + if (!drive_id.empty()) + url += "&supportsAllDrives=true"; + Headers headers; + headers.insert(std::make_pair("Range", "bytes=" + std::to_string(offset) + "-" + std::to_string(offset + size - 1))); + if (auto res = client->Get(url, headers, + [&](const char *data, size_t data_length) + { + body.insert(body.end(), data, data + data_length); + bytes_read += data_length; + if (bytes_read > size) + return false; + return true; + })) + { + if (body.size() != size) + return 0; + memcpy(buffer, body.data(), size); + return 1; + } + else + { + sprintf(this->response, "%s", httplib::to_string(res.error()).c_str()); + } + return 0; + +} + int GDriveClient::Update(const std::string &inputfile, const std::string &path) { bytes_to_download = FS::GetSize(inputfile); diff --git a/source/clients/gdrive.h b/source/clients/gdrive.h index 2b57e18..1615ffd 100644 --- a/source/clients/gdrive.h +++ b/source/clients/gdrive.h @@ -19,6 +19,7 @@ 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 GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset); int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0); int Head(const std::string &path, void *buffer, uint64_t len); int Update(const std::string &inputfile, const std::string &path); diff --git a/source/clients/remote_client.h b/source/clients/remote_client.h index 9eca76f..1d23e47 100644 --- a/source/clients/remote_client.h +++ b/source/clients/remote_client.h @@ -48,6 +48,7 @@ public: virtual int Copy(const std::string &from, const std::string &to) = 0; virtual int Move(const std::string &from, const std::string &to) = 0; virtual int Head(const std::string &path, void *buffer, uint64_t len) = 0; + virtual int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset) = 0; virtual bool FileExists(const std::string &path) = 0; virtual std::vector ListDir(const std::string &path) = 0; virtual std::string GetPath(std::string path1, std::string path2) = 0; diff --git a/source/clients/sftpclient.cpp b/source/clients/sftpclient.cpp index 8fc8206..f763030 100644 --- a/source/clients/sftpclient.cpp +++ b/source/clients/sftpclient.cpp @@ -302,6 +302,29 @@ int SFTPClient::Get(const std::string &outputfile, const std::string &path, uint return 1; } +int SFTPClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset) +{ + int64_t filesize; + if (!Size(path.c_str(), &filesize)) + { + return 0; + } + + LIBSSH2_SFTP_HANDLE *sftp_handle = libssh2_sftp_open(sftp_session, path.c_str(), LIBSSH2_FXF_READ, 0); + if (!sftp_handle) + { + return 0; + } + + libssh2_sftp_seek64(sftp_handle, offset); + int count = libssh2_sftp_read(sftp_handle, (char *)buffer, size); + libssh2_sftp_close(sftp_handle); + if (count != size) + return 0; + + return 1; +} + int SFTPClient::Put(const std::string &inputfile, const std::string &path, uint64_t offset) { char *ptr, *buff; diff --git a/source/clients/sftpclient.h b/source/clients/sftpclient.h index 1c32acd..2223e67 100644 --- a/source/clients/sftpclient.h +++ b/source/clients/sftpclient.h @@ -19,6 +19,7 @@ public: int Rmdir(const std::string &path); int Size(const std::string &path, int64_t *size); int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0); + int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset); int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0); int Rename(const std::string &src, const std::string &dst); int Delete(const std::string &path); diff --git a/source/clients/smbclient.cpp b/source/clients/smbclient.cpp index 7dcb079..6497ada 100644 --- a/source/clients/smbclient.cpp +++ b/source/clients/smbclient.cpp @@ -16,8 +16,6 @@ #include "windows.h" #include "util.h" -#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) - SmbClient::SmbClient() { } @@ -228,6 +226,32 @@ int SmbClient::Get(const std::string &outputfile, const std::string &ppath, uint return 1; } +int SmbClient::GetRange(const std::string &ppath, void *buffer, uint64_t size, uint64_t offset) +{ + std::string path = std::string(ppath); + path = Util::Trim(path, "/"); + int64_t filesize; + if (!Size(path.c_str(), &filesize)) + { + return 0; + } + + struct smb2fh* in = smb2_open(smb2, path.c_str(), O_RDONLY); + if (in == NULL) + { + return 0; + } + + smb2_lseek(smb2, in, offset, SEEK_SET, NULL); + + int count = smb2_read(smb2, in, (uint8_t*)buffer, size); + smb2_close(smb2, in); + if (count != size) + return 0; + + return 1; +} + int SmbClient::Copy(const std::string &ffrom, const std::string &tto) { sprintf(response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]); diff --git a/source/clients/smbclient.h b/source/clients/smbclient.h index bdd1dab..467f0a9 100644 --- a/source/clients/smbclient.h +++ b/source/clients/smbclient.h @@ -23,6 +23,7 @@ public: int Rmdir(const std::string &path, bool recursive); int Size(const std::string &path, int64_t *size); int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0); + int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset); int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0); int Rename(const std::string &src, const std::string &dst); int Delete(const std::string &path); diff --git a/source/clients/webdavclient.cpp b/source/clients/webdavclient.cpp index cd71701..eaa0a4c 100644 --- a/source/clients/webdavclient.cpp +++ b/source/clients/webdavclient.cpp @@ -200,6 +200,21 @@ namespace WebDAV return ret; } + int WebDavClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset) + { + char *buffer_ptr = nullptr; + unsigned long long buffer_size = 0; + + bool ret = client->download_range_to(path, buffer_ptr, buffer_size, offset, offset+size-1); + sprintf(response, "Http Code %ld", client->status_code()); + if (buffer_size != size) + { + return 0; + } + memcpy(buffer, buffer_ptr, size); + return 1; + } + /* * Put - issue a PUT command and send data from input * diff --git a/source/clients/webdavclient.h b/source/clients/webdavclient.h index f481b22..f69bd50 100644 --- a/source/clients/webdavclient.h +++ b/source/clients/webdavclient.h @@ -28,6 +28,7 @@ namespace WebDAV int Rmdir(const std::string &path, bool recursive); int Size(const std::string &path, int64_t *size); int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0); + int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset); int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0); int Rename(const std::string &src, const std::string &dst); int Delete(const std::string &path); diff --git a/source/config.cpp b/source/config.cpp index bdf88bb..86bc535 100644 --- a/source/config.cpp +++ b/source/config.cpp @@ -144,7 +144,7 @@ namespace CONFIG "Site 11", "Site 12", "Site 13", "Site 14", "Site 15", "Site 16", "Site 17", "Site 18", "Site 19", "Site 20"}; http_servers = {HTTP_SERVER_APACHE, HTTP_SERVER_MS_IIS, HTTP_SERVER_NGINX, HTTP_SERVER_NPX_SERVE}; - text_file_extensions = { ".txt", ".ini", ".json", ".xml", ".html", ".xhtml", ".conf" }; + text_file_extensions = { ".txt", ".ini", ".log", ".json", ".xml", ".html", ".xhtml", ".conf", ".config" }; image_file_extensions = { ".bmp", ".jpg", ".jpeg", ".png", ".webp" }; OpenIniFile(CONFIG_INI_FILE); diff --git a/source/fs.cpp b/source/fs.cpp index 7fa68e1..d381436 100644 --- a/source/fs.cpp +++ b/source/fs.cpp @@ -131,22 +131,18 @@ namespace FS std::vector Load(const std::string &path) { - FILE *fd = fopen(path.c_str(), "r"); + FILE *fd = fopen(path.c_str(), "rb"); if (fd == nullptr) return std::vector(0); - - const auto size = fseek(fd, 0, SEEK_END); - fseek(fd, 0, SEEK_SET); - + const auto size = GetSize(path); std::vector data(size); - const auto read = fread(data.data(), data.size(), 1, fd); + const auto read = fread(data.data(), 1, data.size(), fd); fclose(fd); if (read < 0) return std::vector(0); data.resize(read); - return data; } diff --git a/source/installer.cpp b/source/installer.cpp index 8f487db..eea9cbd 100644 --- a/source/installer.cpp +++ b/source/installer.cpp @@ -383,18 +383,13 @@ namespace INSTALLER return 0; } - bool ExtractLocalPkg(const std::string &filename, pkg_header *pkg_hdr, const std::string sfo_path, const std::string icon_path) + bool ExtractLocalPkg(const std::string &filename, const std::string sfo_path, const std::string icon_path) { pkg_header tmp_hdr; - pkg_header *p_hdr = pkg_hdr; - if (p_hdr == nullptr) - { - FS::Head(filename, &tmp_hdr, sizeof(pkg_header)); - p_hdr = &tmp_hdr; - } + FS::Head(filename, &tmp_hdr, sizeof(pkg_header)); - size_t entry_count = BE32(p_hdr->pkg_entry_count); - uint32_t entry_table_offset = BE32(p_hdr->pkg_table_offset); + size_t entry_count = BE32(tmp_hdr.pkg_entry_count); + uint32_t entry_table_offset = BE32(tmp_hdr.pkg_table_offset); uint64_t entry_table_size = entry_count * sizeof(pkg_table_entry); void *entry_table_data = malloc(entry_table_size); @@ -458,4 +453,80 @@ namespace INSTALLER FS::Close(fd); return true; } + + bool ExtractRemotePkg(const std::string &filename, const std::string sfo_path, const std::string icon_path) + { + pkg_header tmp_hdr; + if (!remoteclient->Head(filename, &tmp_hdr, sizeof(pkg_header))) + return false; + + size_t entry_count = BE32(tmp_hdr.pkg_entry_count); + uint32_t entry_table_offset = BE32(tmp_hdr.pkg_table_offset); + uint64_t entry_table_size = entry_count * sizeof(pkg_table_entry); + void *entry_table_data = malloc(entry_table_size); + + if (!remoteclient->GetRange(filename, entry_table_data, entry_table_size, entry_table_offset)) + return false; + + pkg_table_entry *entries = (pkg_table_entry *)entry_table_data; + void* param_sfo_data = NULL; + uint32_t param_sfo_offset = 0; + uint32_t param_sfo_size = 0; + void *icon0_png_data = NULL; + uint32_t icon0_png_offset = 0; + uint32_t icon0_png_size = 0; + short items = 0; + for (size_t i = 0; i < entry_count; ++i) + { + switch (BE32(entries[i].id)) + { + case PKG_ENTRY_ID__PARAM_SFO: + param_sfo_offset = BE32(entries[i].offset); + param_sfo_size = BE32(entries[i].size); + items++; + break; + case PKG_ENTRY_ID__ICON0_PNG: + icon0_png_offset = BE32(entries[i].offset); + icon0_png_size = BE32(entries[i].size); + items++; + break; + default: + continue; + } + + if (items == 2) + break; + } + free(entry_table_data); + + if (param_sfo_offset > 0 && param_sfo_size > 0) + { + param_sfo_data = malloc(param_sfo_size); + FILE *out = FS::Create(sfo_path); + if (!remoteclient->GetRange(filename, param_sfo_data, param_sfo_size, param_sfo_offset)) + { + FS::Close(out); + return false; + } + FS::Write(out, param_sfo_data, param_sfo_size); + FS::Close(out); + free(param_sfo_data); + } + + if (icon0_png_offset > 0 && icon0_png_size > 0) + { + icon0_png_data = malloc(icon0_png_size); + FILE *out = FS::Create(icon_path); + if (!remoteclient->GetRange(filename, icon0_png_data, icon0_png_size, icon0_png_offset)) + { + FS::Close(out); + return false; + } + FS::Write(out, icon0_png_data, icon0_png_size); + FS::Close(out); + free(icon0_png_data); + } + + return true; + } } \ No newline at end of file diff --git a/source/installer.h b/source/installer.h index 9de1d02..c957f3b 100644 --- a/source/installer.h +++ b/source/installer.h @@ -123,5 +123,6 @@ namespace INSTALLER std::string getRemoteUrl(const std::string filename, bool encodeUrl = false); int InstallRemotePkg(const std::string &filename, pkg_header *header); int InstallLocalPkg(const std::string &filename, pkg_header *header, bool remove_after_install = false); - bool ExtractLocalPkg(const std::string &filename, pkg_header *pkg_header, const std::string sfo_path, const std::string icon_path); + bool ExtractLocalPkg(const std::string &filename, const std::string sfo_path, const std::string icon_path); + bool ExtractRemotePkg(const std::string &filename, const std::string sfo_path, const std::string icon_path); } \ No newline at end of file diff --git a/source/lang.cpp b/source/lang.cpp index 353878c..051d67c 100644 --- a/source/lang.cpp +++ b/source/lang.cpp @@ -156,6 +156,7 @@ char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE] = { "Set Default Folder", // STR_SET_DEFAULT_DIRECTORY "has being set as default direcotry", // STR_SET_DEFAULT_DIRECTORY_MSG "View Image", // STR_VIEW_IMAGE + "Package Information", // STR_VIEW_PKG_INFO }; bool needs_extended_font = false; diff --git a/source/lang.h b/source/lang.h index ca8ff79..884c075 100644 --- a/source/lang.h +++ b/source/lang.h @@ -147,7 +147,8 @@ FUNC(STR_SHOW_HIDDEN_FILES) \ FUNC(STR_SET_DEFAULT_DIRECTORY) \ FUNC(STR_SET_DEFAULT_DIRECTORY_MSG) \ - FUNC(STR_VIEW_IMAGE) + FUNC(STR_VIEW_IMAGE) \ + FUNC(STR_VIEW_PKG_INFO) #define GET_VALUE(x) x, #define GET_STRING(x) #x, @@ -157,7 +158,7 @@ enum FOREACH_STR(GET_VALUE) }; -#define LANG_STRINGS_NUM 144 +#define LANG_STRINGS_NUM 145 #define LANG_ID_SIZE 64 #define LANG_STR_SIZE 384 extern char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE]; diff --git a/source/sfo.cpp b/source/sfo.cpp index fb863cd..6c71f99 100644 --- a/source/sfo.cpp +++ b/source/sfo.cpp @@ -27,4 +27,38 @@ namespace SFO { return {}; } + + std::map GetParams(const char* buffer, size_t size) + { + std::map out; + + if (size < sizeof(SfoHeader)) + return out; + + const SfoHeader* header = reinterpret_cast(buffer); + const SfoEntry* entries = + reinterpret_cast(buffer + sizeof(SfoHeader)); + + if (header->magic != SFO_MAGIC) + return out; + + if (size < sizeof(SfoHeader) + header->count * sizeof(SfoEntry)) + return out; + + for (uint32_t i = 0; i < header->count; i++) { + const char* key = reinterpret_cast(buffer + header->keyofs + entries[i].nameofs); + if (entries[i].type == 2) + { + const char* value = reinterpret_cast(buffer + header->valofs + entries[i].dataofs); + out.insert(std::make_pair(key, value)); + } + else + { + uint32_t *value = (uint32_t *)(buffer + header->valofs + entries[i].dataofs); + out.insert(std::make_pair(key, std::to_string(*value))); + } + } + + return out; + } } \ No newline at end of file diff --git a/source/sfo.h b/source/sfo.h index 5662d0e..761ac56 100644 --- a/source/sfo.h +++ b/source/sfo.h @@ -5,6 +5,7 @@ #include #include +#include struct SfoHeader { @@ -27,6 +28,7 @@ struct SfoEntry namespace SFO { const char* GetString(const char* buffer, size_t size, const char *name); + std::map GetParams(const char* buffer, size_t size); } #endif \ No newline at end of file diff --git a/source/windows.cpp b/source/windows.cpp index 6cf0ab9..6d8648a 100644 --- a/source/windows.cpp +++ b/source/windows.cpp @@ -17,6 +17,7 @@ #include "IconsFontAwesome6.h" #include "OpenFontIcons.h" #include "textures.h" +#include "sfo.h" #define MAX_IMAGE_HEIGHT 980 #define MAX_IMAGE_WIDTH 1820 @@ -85,9 +86,12 @@ int edit_line_to_select = -1; std::string copy_text; // Images varaibles -bool view_image; +bool view_image= false; Tex texture; +bool show_pkg_info = false; +std::map sfo_params; + // Overwrite dialog variables bool dont_prompt_overwrite = false; bool dont_prompt_overwrite_cb = false; @@ -591,9 +595,13 @@ namespace Windows { selected_action = ACTION_VIEW_LOCAL_IMAGE; } + else if (text_file_extensions.find(ext) != text_file_extensions.end()) + { + selected_action = ACTION_LOCAL_EDIT; + } else if (ext.compare(".pkg") == 0) { - INSTALLER::ExtractLocalPkg(selected_local_file.path, nullptr, TMP_SFO_PATH, TMP_ICON_PATH); + selected_action = ACTION_VIEW_LOCAL_PKG; } } } @@ -753,6 +761,14 @@ namespace Windows { selected_action = ACTION_VIEW_REMOTE_IMAGE; } + else if (text_file_extensions.find(ext) != text_file_extensions.end()) + { + selected_action = ACTION_REMOTE_EDIT; + } + else if (ext.compare(".pkg") == 0) + { + selected_action = ACTION_VIEW_REMOTE_PKG; + } } } } @@ -1037,32 +1053,14 @@ namespace Windows } if (ImGui::Selectable(lang_strings[STR_EDIT], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0))) { - bool can_edit = true; if (local_browser_selected) { - if (selected_local_file.file_size > max_edit_file_size) - can_edit = false; - else - { - snprintf(edit_file, 255, "%s", selected_local_file.path); - FS::LoadText(&edit_buffer, selected_local_file.path); - } + selected_action = ACTION_LOCAL_EDIT; } else { - if (selected_remote_file.file_size > max_edit_file_size) - can_edit = false; - else if (remoteclient != nullptr && remoteclient->Get(TMP_EDITOR_FILE, selected_remote_file.path)) - { - snprintf(edit_file, 255, "%s", selected_remote_file.path); - FS::LoadText(&edit_buffer, TMP_EDITOR_FILE); - } + selected_action = ACTION_REMOTE_EDIT; } - if (can_edit) - editor_inprogress = true; - else - sprintf(status_message, "%s %d", lang_strings[STR_MAX_EDIT_FILE_SIZE_MSG], max_edit_file_size); - editor_modified = false; SetModalMode(false); ImGui::CloseCurrentPopup(); } @@ -1734,7 +1732,7 @@ namespace Windows ImGui::SetNextWindowPos(image_pos); ImGui::SetNextWindowSizeConstraints(image_size, view_size, NULL, NULL); - if (ImGui::BeginPopupModal(lang_strings[STR_VIEW_IMAGE], NULL, ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_AlwaysAutoResize)) + if (ImGui::BeginPopupModal(lang_strings[STR_VIEW_IMAGE], NULL, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::Image(texture.id, image_size); if (ImGui::IsKeyPressed(ImGuiKey_GamepadFaceRight, false)) @@ -1749,6 +1747,69 @@ namespace Windows } } + void ShowPackageInfoDialog() + { + if (!paused) + saved_selected_browser = selected_browser; + if (show_pkg_info) + { + ImGuiIO &io = ImGui::GetIO(); + (void)io; + ImGuiStyle *style = &ImGui::GetStyle(); + ImVec4 *colors = style->Colors; + + SetModalMode(true); + ImGui::OpenPopup(lang_strings[STR_VIEW_PKG_INFO]); + + ImGui::SetNextWindowPos(ImVec2(360, 240)); + ImGui::SetNextWindowSizeConstraints(ImVec2(1200, 300), ImVec2(1200, 600), NULL, NULL); + if (ImGui::BeginPopupModal(lang_strings[STR_VIEW_PKG_INFO], NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize)) + { + ImGui::Image(texture.id, ImVec2(400, 400)); + ImGui::SameLine(); + + BeginGroupPanel("SFO Attributes", ImVec2(780, 600)); + ImGui::PushTextWrapPos(1180); + for (std::map::iterator it = sfo_params.begin(); it != sfo_params.end(); ++it) + { + if (!it->second.empty()) + { + ImGui::TextColored(colors[ImGuiCol_ButtonHovered],"%s:", it->first.c_str()); + ImGui::SameLine(); + ImGui::Text("%s", it->second.c_str()); + } + } + ImGui::PopTextWrapPos(); + EndGroupPanel(); + + if (saved_selected_browser & REMOTE_BROWSER || + (saved_selected_browser & LOCAL_BROWSER && (strncmp(selected_local_file.path, "/data/", 6) == 0 || strncmp(selected_local_file.path, "/mnt/usb", 8) == 0))) + { + ImGui::SetCursorPos(ImVec2(7, 420)); + if (ImGui::Button(lang_strings[STR_INSTALL], ImVec2(400, 0))) + { + if (saved_selected_browser & REMOTE_BROWSER) + selected_action = ACTION_INSTALL_REMOTE_PKG; + else + selected_action = ACTION_INSTALL_LOCAL_PKG; + show_pkg_info = false; + SetModalMode(false); + ImGui::CloseCurrentPopup(); + } + } + + if (ImGui::IsKeyPressed(ImGuiKey_GamepadFaceRight, false)) + { + show_pkg_info = false; + SetModalMode(false); + Textures::Free(&texture); + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + } + } + void MainWindow() { Windows::SetupWindow(); @@ -1769,12 +1830,14 @@ namespace Windows ShowEditorDialog(); ShowSettingsDialog(); ShowImageDialog(); + ShowPackageInfoDialog(); } ImGui::End(); } void ExecuteActions() { + std::vector sfo; switch (selected_action) { case ACTION_CHANGE_LOCAL_DIRECTORY: @@ -2053,6 +2116,48 @@ namespace Windows } selected_action = ACTION_NONE; break; + case ACTION_LOCAL_EDIT: + if (selected_local_file.file_size > max_edit_file_size) + sprintf(status_message, "%s %d", lang_strings[STR_MAX_EDIT_FILE_SIZE_MSG], max_edit_file_size); + else + { + snprintf(edit_file, 255, "%s", selected_local_file.path); + FS::LoadText(&edit_buffer, selected_local_file.path); + editor_inprogress = true; + } + editor_modified = false; + selected_action = ACTION_NONE; + break; + case ACTION_REMOTE_EDIT: + if (selected_remote_file.file_size > max_edit_file_size) + sprintf(status_message, "%s %d", lang_strings[STR_MAX_EDIT_FILE_SIZE_MSG], max_edit_file_size); + else if (remoteclient != nullptr && remoteclient->Get(TMP_EDITOR_FILE, selected_remote_file.path)) + { + snprintf(edit_file, 255, "%s", selected_remote_file.path); + FS::LoadText(&edit_buffer, TMP_EDITOR_FILE); + editor_inprogress = true; + } + editor_modified = false; + selected_action = ACTION_NONE; + break; + case ACTION_VIEW_LOCAL_PKG: + INSTALLER::ExtractLocalPkg(selected_local_file.path, TMP_SFO_PATH, TMP_ICON_PATH); + Textures::LoadImageFile(TMP_ICON_PATH, &texture); + sfo = FS::Load(TMP_SFO_PATH); + sfo_params = SFO::GetParams(sfo.data(), sfo.size()); + show_pkg_info = true; + selected_action = ACTION_NONE; + break; + case ACTION_VIEW_REMOTE_PKG: + if (INSTALLER::ExtractRemotePkg(selected_remote_file.path, TMP_SFO_PATH, TMP_ICON_PATH)) + { + Textures::LoadImageFile(TMP_ICON_PATH, &texture); + sfo = FS::Load(TMP_SFO_PATH); + sfo_params = SFO::GetParams(sfo.data(), sfo.size()); + show_pkg_info = true; + } + selected_action = ACTION_NONE; + break; default: break; }