mirror of
https://github.com/Team-Resurgent/webMAN-MOD.git
synced 2026-08-15 11:18:26 -07:00
- Added a condition to don't close the PS3 browser if /download.ps3 or /install.ps3 is called directly, instead of using /xmb.ps3 (issue #877) - Fixed the breadcrumb trail when the path is an URL
492 lines
13 KiB
C
492 lines
13 KiB
C
#define IS_INSTALLING (View_Find("game_plugin") != 0)
|
|
#define IS_INSTALLING_NAS (View_Find("nas_plugin") != 0)
|
|
#define IS_DOWNLOADING (View_Find("download_plugin") != 0)
|
|
|
|
#define PKG_MAGIC 0x7F504B47
|
|
#define XMM0 0x584d4d30
|
|
|
|
#ifdef PKG_HANDLER
|
|
|
|
// /install_ps3<pkg-path> Keeps pkg after installation
|
|
// /install.ps3<pkg-path> Deletes pkg after installation
|
|
// /install.ps3<pkg-path>? Installs only if it's a new game, othewise navigates to the installation folder
|
|
// /install.ps3?url=<url> Downloads pkg to /dev_hdd0/packages & installs the pkg after download (pkg is deleted after installation)
|
|
// /install_ps3?url=<url> Downloads pkg to /dev_hdd0/packages & installs the pkg after download (pkg is kept after installation)
|
|
// /install.ps3?to=<path>&url=<url> Same as /download.ps3
|
|
|
|
// /download.ps3?url=<url> Downloads file to /dev_hdd0/packages. pkg files are downloaded to /dev_hdd0/tmp/downloader then moved to /dev_hdd0/packages
|
|
// /download.ps3?to=<path>&url=<url> Downloads file to <path>
|
|
|
|
#include <cell/http.h>
|
|
|
|
extern wchar_t *stdc_F06EED36(wchar_t *ptr, wchar_t wc, size_t num); // wmemset()
|
|
#define wmemset stdc_F06EED36
|
|
|
|
#define MAX_URL_LEN 360
|
|
#define MAX_DLPATH_LEN 240
|
|
|
|
#define MAX_PKGPATH_LEN 240
|
|
static char pkg_path[MAX_PKGPATH_LEN];
|
|
|
|
static wchar_t pkg_durl[MAX_URL_LEN];
|
|
static wchar_t pkg_dpath[MAX_DLPATH_LEN];
|
|
|
|
static u8 pkg_dcount = 0;
|
|
static u8 pkg_auto_install = 0;
|
|
static bool pkg_delete_after_install = true;
|
|
static char install_path[64];
|
|
static time_t pkg_install_time = 0;
|
|
|
|
static bool install_in_progress = false;
|
|
static bool installing_pkg = false;
|
|
|
|
typedef struct {
|
|
u32 magic; // 0x7F504B47 //
|
|
u32 version;
|
|
u16 sdk_type;
|
|
u16 SCE_header_type;
|
|
u32 meta_offset;
|
|
u64 size; // size of sce_hdr + sizeof meta_hdr
|
|
u64 pkg_size;
|
|
u64 unk1;
|
|
u64 data_size;
|
|
char publisher[6]; // ??
|
|
char sep;
|
|
char title_id[9];
|
|
} _pkg_header;
|
|
|
|
static u64 get_pkg_size_and_install_time(const char *pkgfile)
|
|
{
|
|
_pkg_header pkg_header;
|
|
|
|
int fd; *install_path = pkg_header.pkg_size = pkg_install_time = 0;
|
|
|
|
if(cellFsOpen(pkgfile, CELL_FS_O_RDONLY, &fd, NULL, 0) == CELL_FS_SUCCEEDED)
|
|
{
|
|
if(cellFsRead(fd, (void *)&pkg_header, sizeof(pkg_header), NULL) == CELL_FS_SUCCEEDED && pkg_header.magic == PKG_MAGIC)
|
|
{
|
|
sprintf(install_path, "%s%s%s", HDD0_GAME_DIR, pkg_header.title_id, "/PS3LOGO.DAT");
|
|
|
|
struct CellFsStat s;
|
|
if(cellFsStat(install_path, &s) == CELL_FS_SUCCEEDED) pkg_install_time = s.st_mtime; // prevents pkg deletion if user cancels install
|
|
|
|
install_path[24] = '\0';
|
|
}
|
|
cellFsClose(fd);
|
|
}
|
|
|
|
return pkg_header.pkg_size; // also returns module variableS: pkg_install_time & install_path
|
|
}
|
|
|
|
static void wait_for_xml_download(char *filename, char *param)
|
|
{
|
|
char *xml = strstr(filename, ".xm!");
|
|
if(xml)
|
|
{
|
|
xml = strchr(filename, '~');
|
|
|
|
struct CellFsStat s; u64 size = 475000; if(xml) size = val(xml + 1); else xml = strstr(filename, ".xm!");
|
|
/*
|
|
while(IS_DOWNLOADING)
|
|
{
|
|
sys_timer_sleep(1);
|
|
}
|
|
*/
|
|
for(u8 retry = 0; retry < 15; retry++)
|
|
{if(!working || (cellFsStat(filename, &s) == CELL_FS_SUCCEEDED && s.st_size >= size)) break; sys_ppu_thread_sleep(2);}
|
|
|
|
if(s.st_size < size) {cellFsUnlink(filename); return;}
|
|
|
|
strcpy(param, filename); strcpy(xml, ".xml");
|
|
cellFsUnlink(filename);
|
|
cellFsRename(param, filename);
|
|
|
|
#ifdef VIRTUAL_PAD
|
|
if(IS_DOWNLOADING) press_cancel_button(0);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static void wait_for_pkg_install(void)
|
|
{
|
|
sys_ppu_thread_sleep(5);
|
|
|
|
while (working && IS_INSTALLING) sys_ppu_thread_sleep(2);
|
|
|
|
time_t install_time = pkg_install_time; // set time before install
|
|
get_pkg_size_and_install_time(pkg_path); // get time after install
|
|
|
|
if(working && pkg_delete_after_install && islike(pkg_path, INT_HDD_ROOT_PATH) && (strstr(pkg_path, "/GAME") == NULL))
|
|
{
|
|
if(pkg_install_time != install_time) cellFsUnlink(pkg_path);
|
|
}
|
|
|
|
if(do_restart && (pkg_install_time == install_time)) do_restart = false; // installation canceled
|
|
}
|
|
|
|
static int get_xmm0_interface(void)
|
|
{
|
|
//if(xmm0_interface == 0) // getting xmb_plugin xmm0 interface for loading plugin sprx
|
|
{
|
|
xmm0_interface = (xmb_plugin_xmm0 *)plugin_GetInterface(View_Find("xmb_plugin"), XMM0);
|
|
if(xmm0_interface == 0) return FAILED;
|
|
}
|
|
return CELL_OK;
|
|
}
|
|
|
|
static void LoadBlankPage(void)
|
|
{
|
|
//if(game_ext_interface == 0) // test if game_ext_plugin is loaded for interface access
|
|
{
|
|
game_ext_interface = (game_ext_plugin_interface *)plugin_GetInterface(View_Find("game_ext_plugin"), 1);
|
|
if(game_ext_interface == 0) return;
|
|
}
|
|
game_ext_interface->LoadPage();
|
|
}
|
|
|
|
static int LoadPluginById(int id, void *handler)
|
|
{
|
|
if(get_xmm0_interface()) return FAILED;
|
|
|
|
return xmm0_interface->LoadPlugin3(id, handler, 0);
|
|
}
|
|
|
|
static void unloadSysPluginCallback(void)
|
|
{
|
|
//Add potential callback process
|
|
//show_msg((char *)"plugin shutdown via xmb call launched");
|
|
}
|
|
|
|
static void UnloadPluginById(int id)
|
|
{
|
|
if(get_xmm0_interface()) return;
|
|
|
|
u8 retry = 0;
|
|
|
|
while(xmm0_interface->IsPluginViewAvailable(id))
|
|
{
|
|
xmm0_interface->Shutdown(id, (void *)unloadSysPluginCallback, 1);
|
|
sys_ppu_thread_usleep(100000); if(++retry > 100) break;
|
|
}
|
|
}
|
|
|
|
static void unload_system_plugins(void)
|
|
{
|
|
UnloadPluginById(nas_plugin);
|
|
UnloadPluginById(wboard_plugin);
|
|
UnloadPluginById(np_trophy_plugin);
|
|
UnloadPluginById(sysconf_plugin);
|
|
}
|
|
|
|
static void unload_plugin_modules(bool all)
|
|
{
|
|
// Unload conflicting plugins
|
|
if(View_Find("webbrowser_plugin")) UnloadPluginById(webbrowser_plugin);
|
|
if(View_Find("webrender_plugin")) UnloadPluginById(webrender_plugin);
|
|
|
|
if(all)
|
|
{
|
|
from_xmb_ps3 = false;
|
|
unload_system_plugins();
|
|
}
|
|
|
|
#ifdef VIRTUAL_PAD
|
|
if(IS_ON_XMB)
|
|
{
|
|
press_cancel_button(0);
|
|
}
|
|
#endif
|
|
|
|
if(!get_explore_interface()) return;
|
|
|
|
exec_xmb_command("close_all_list");
|
|
if(all)
|
|
{
|
|
sys_ppu_thread_sleep(2);
|
|
exec_xmb_command2("focus_category %s", "game");
|
|
exec_xmb_command2("reload_category %s", "game");
|
|
}
|
|
}
|
|
|
|
static void downloadPKG_thread(void)
|
|
{
|
|
//if(download_interface == 0) // test if download_interface is loaded for interface access
|
|
{
|
|
download_interface = (download_plugin_interface *)plugin_GetInterface(View_Find("download_plugin"), 1);
|
|
if(download_interface == 0) return;
|
|
}
|
|
download_interface->DownloadURL(0, pkg_durl, pkg_dpath);
|
|
}
|
|
|
|
static int download_file(const char *param, char *msg)
|
|
{
|
|
int ret = FAILED;
|
|
|
|
s32 net_enabled = 0;
|
|
xnet()->GetSettingNet_enable(&net_enabled);
|
|
|
|
if(!net_enabled)
|
|
{
|
|
sprintf(msg, "ERROR: %s", "network disabled");
|
|
return ret;
|
|
}
|
|
|
|
if(IS_INGAME)
|
|
{
|
|
sprintf(msg, "ERROR: %s", "download from XMB");
|
|
return ret;
|
|
}
|
|
|
|
char *msg_durl = msg;
|
|
char *msg_dpath = msg + MAX_URL_LEN + 16;
|
|
|
|
sprintf(msg_durl, "ERROR: %s", "Invalid URL");
|
|
sprintf(msg_dpath, "Download canceled");
|
|
|
|
char pdurl[MAX_URL_LEN];
|
|
char pdpath[MAX_DLPATH_LEN];
|
|
|
|
wmemset(pkg_durl, 0, MAX_URL_LEN); // Use wmemset from stdc.h instead of reinitialising wchar_t with a loop.
|
|
wmemset(pkg_dpath, 0, MAX_DLPATH_LEN);
|
|
|
|
_memset(pdurl, MAX_URL_LEN);
|
|
_memset(pdpath, MAX_DLPATH_LEN);
|
|
|
|
int len;
|
|
size_t conv_num = 0;
|
|
|
|
if(islike(param, "?to=")) //Use of the optional parameter
|
|
{
|
|
len = get_param("&url=", pdurl, param, MAX_DLPATH_LEN); if(!islike(pdurl, "http")) goto end_download_process;
|
|
conv_num = mbstowcs((wchar_t *)pkg_durl, (const char *)pdurl, len + 1); //size_t stdc_FCAC2E8E(wchar_t *dest, const char *src, size_t max)
|
|
|
|
len = get_param("?to=", pdpath, param, MAX_DLPATH_LEN); if(*pdpath != '/') goto end_download_process;
|
|
filepath_check(pdpath);
|
|
}
|
|
else if(islike(param, "?url="))
|
|
{
|
|
len = get_param("?url=", pdurl, param, MAX_DLPATH_LEN); if(!islike(pdurl, "http")) goto end_download_process;
|
|
conv_num = mbstowcs((wchar_t *)pkg_durl,(const char *)pdurl, len + 1); //size_t stdc_FCAC2E8E(wchar_t *dest, const char *src, size_t max)
|
|
|
|
len = sprintf(pdpath, "%s", is_ext(pdurl, ".p3t") ? "/dev_hdd0/theme" : DEFAULT_PKG_PATH);
|
|
}
|
|
|
|
if(conv_num)
|
|
{
|
|
filepath_check(pdpath); // replace $USERID$ with current user id & remove invalid chars
|
|
|
|
mkdir_tree(pdpath);
|
|
|
|
if(isDir(pdpath) || (cellFsMkdir(pdpath, DMODE) == CELL_FS_SUCCEEDED)) ;
|
|
|
|
else if(isDir(DEFAULT_PKG_PATH) || cellFsMkdir(DEFAULT_PKG_PATH, DMODE) == CELL_FS_SUCCEEDED)
|
|
{
|
|
len = sprintf(pdpath, DEFAULT_PKG_PATH);
|
|
}
|
|
else
|
|
{
|
|
len = sprintf(pdpath, INT_HDD_ROOT_PATH);
|
|
}
|
|
|
|
sprintf(msg_dpath, "To: %s", pdpath);
|
|
if(IS(pdpath, DEFAULT_PKG_PATH) && strstr(pdurl, ".pkg"))
|
|
{
|
|
len = sprintf(pdpath, TEMP_DOWNLOAD_PATH); pkg_dcount++;
|
|
}
|
|
|
|
conv_num = mbstowcs((wchar_t *)pkg_dpath, (const char *)pdpath, len + 1);
|
|
|
|
if(conv_num)
|
|
{
|
|
unload_system_plugins();
|
|
|
|
sys_ppu_thread_sleep(3);
|
|
|
|
mkdir_tree(pdpath); cellFsMkdir(pdpath, DMODE);
|
|
|
|
sprintf(msg_durl, "Downloading %s", pdurl);
|
|
|
|
LoadPluginById(download_plugin, (void *)downloadPKG_thread);
|
|
ret = CELL_OK;
|
|
}
|
|
else
|
|
sprintf(msg_durl, "ERROR: %s", "Setting storage location");
|
|
}
|
|
|
|
end_download_process:
|
|
sprintf(msg, "%s\n%s", msg_durl, msg_dpath);
|
|
return ret;
|
|
}
|
|
|
|
static void installPKG_thread(void)
|
|
{
|
|
LoadBlankPage();
|
|
|
|
installing_pkg = true;
|
|
|
|
if(is_ext(pkg_path, ".p3t"))
|
|
game_ext_interface->installTheme(pkg_path, (char*)"");
|
|
else
|
|
game_ext_interface->installPKG(pkg_path);
|
|
|
|
installing_pkg = false;
|
|
}
|
|
|
|
static int installPKG(const char *pkgpath, char *msg)
|
|
{
|
|
int ret = FAILED;
|
|
|
|
unload_system_plugins();
|
|
|
|
if(IS_INGAME)
|
|
{
|
|
unload_plugin_modules(true);
|
|
|
|
if(IS_INGAME)
|
|
{
|
|
sprintf(msg, "ERROR: %s", "install from XMB");
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
size_t pkg_path_len = strlen(pkgpath);
|
|
|
|
if (pkg_path_len < MAX_PKGPATH_LEN)
|
|
{
|
|
#ifdef COBRA_ONLY
|
|
if(islike(pkgpath, "/net"))
|
|
{
|
|
cache_file_to_hdd((char*)pkgpath, pkg_path, "/tmp/downloader", msg); pkg_dcount++;
|
|
}
|
|
else
|
|
#endif
|
|
if(*pkgpath == '?')
|
|
{
|
|
pkg_auto_install++;
|
|
return download_file(pkgpath, msg);
|
|
}
|
|
else
|
|
snprintf(pkg_path, MAX_PKGPATH_LEN, "%s", pkgpath);
|
|
|
|
if(file_exists(pkg_path))
|
|
{
|
|
if(is_ext(pkg_path, ".pkg") || is_ext(pkg_path, ".p3t")) //check if file has a .pkg extension or not and treat accordingly
|
|
{
|
|
LoadPluginById(game_ext_plugin, (void *)installPKG_thread);
|
|
|
|
get_pkg_size_and_install_time(pkg_path); // set original pkg_install_time
|
|
|
|
sprintf(msg, "%s%s\nTo: %s", "Installing ", pkg_path, install_path);
|
|
|
|
ret = CELL_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(ret) sprintf(msg, "ERROR: %s", pkgpath);
|
|
return ret;
|
|
}
|
|
|
|
static char *INSTALL_PKG_PATH; // input parameter of installPKG_combo_thread
|
|
|
|
static void installPKG_combo_thread(__attribute__((unused)) u64 arg)
|
|
{
|
|
if(install_in_progress && installing_pkg && IS_INSTALLING) return;
|
|
|
|
install_in_progress = true;
|
|
|
|
int fd, ret = FAILED;
|
|
|
|
if(cellFsOpendir(INSTALL_PKG_PATH, &fd) == CELL_FS_SUCCEEDED)
|
|
{
|
|
CellFsDirent dir; u64 read_e;
|
|
|
|
char pkgfile[MAX_PKGPATH_LEN];
|
|
u16 plen = sprintf(pkgfile, "%s/", INSTALL_PKG_PATH);
|
|
char *path_file = pkgfile + plen;
|
|
|
|
while(working && (cellFsReaddir(fd, &dir, &read_e) == CELL_FS_SUCCEEDED) && (read_e > 0))
|
|
{
|
|
if(is_ext(dir.d_name, ".pkg"))
|
|
{
|
|
strcpy(path_file, dir.d_name);
|
|
|
|
char msg[MAX_PATH_LEN];
|
|
ret = installPKG(pkgfile, msg); if(!(webman_config->minfo & 1)) show_msg(msg);
|
|
if(ret == CELL_OK) wait_for_pkg_install();
|
|
|
|
ret = CELL_OK;
|
|
}
|
|
}
|
|
cellFsClosedir(fd);
|
|
|
|
if(ret == FAILED) { BEEP2 }
|
|
}
|
|
|
|
sys_ppu_thread_sleep(2);
|
|
install_in_progress = false;
|
|
|
|
sys_ppu_thread_exit(0);
|
|
}
|
|
|
|
static void installPKG_all(const char *path, bool delete_after_install)
|
|
{
|
|
pkg_delete_after_install = delete_after_install;
|
|
|
|
if(!install_in_progress && IS_ON_XMB)
|
|
{
|
|
INSTALL_PKG_PATH = (char*)path;
|
|
check_path_tags(INSTALL_PKG_PATH);
|
|
|
|
if(isDir(INSTALL_PKG_PATH))
|
|
{
|
|
sys_ppu_thread_t thread_id;
|
|
sys_ppu_thread_create(&thread_id, installPKG_combo_thread, NULL, THREAD_PRIO, THREAD_STACK_SIZE_INSTALL_PKG, SYS_PPU_THREAD_CREATE_NORMAL, THREAD_NAME_INSTALLPKG);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void poll_downloaded_pkg_files(char *msg)
|
|
{
|
|
if(pkg_dcount)
|
|
{
|
|
CellFsDirent entry; u64 read_e; int fd; u16 pkg_count = 0;
|
|
|
|
if(cellFsOpendir(TEMP_DOWNLOAD_PATH, &fd) == CELL_FS_SUCCEEDED)
|
|
{
|
|
char *dlfile = msg;
|
|
|
|
int plen = sprintf(dlfile, "%s", TEMP_DOWNLOAD_PATH);
|
|
|
|
while(working && (cellFsReaddir(fd, &entry, &read_e) == CELL_FS_SUCCEEDED) && (read_e > 0))
|
|
{
|
|
if(is_ext(entry.d_name, ".pkg"))
|
|
{
|
|
sprintf(dlfile + plen, "%s", entry.d_name); pkg_count++;
|
|
cellFsChmod(dlfile, MODE);
|
|
|
|
u64 pkg_size = get_pkg_size_and_install_time(dlfile); if(pkg_size == 0) continue;
|
|
|
|
struct CellFsStat s;
|
|
if(cellFsStat(dlfile, &s) == CELL_FS_SUCCEEDED && pkg_size == s.st_size)
|
|
{
|
|
char pkgfile[MAX_PATH_LEN];
|
|
u16 pkg_len = sprintf(pkgfile, "%s%s", DEFAULT_PKG_PATH, entry.d_name);
|
|
for(u8 retry = 1; retry < 255; retry++)
|
|
{
|
|
if(cellFsRename(dlfile, pkgfile) == CELL_FS_SUCCEEDED) break;
|
|
sprintf(pkgfile + pkg_len - 4, " (%i).pkg", retry);
|
|
}
|
|
|
|
if(pkg_count) pkg_count--, pkg_dcount--;
|
|
|
|
if(pkg_auto_install) {pkg_auto_install--; installPKG(pkgfile, msg); wait_for_pkg_install();}
|
|
}
|
|
}
|
|
}
|
|
cellFsClosedir(fd);
|
|
}
|
|
}
|
|
}
|
|
#endif // #ifdef PKG_HANDLER
|