Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0dac26d98c | |||
| 1f2b27b52a |
+1
-1
@@ -62,7 +62,7 @@ add_executable(ezremote_client
|
||||
|
||||
add_self(ezremote_client)
|
||||
|
||||
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.08" 32 0)
|
||||
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.09" 32 0)
|
||||
|
||||
target_link_libraries(ezremote_client
|
||||
c
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# ezRemote Client
|
||||
|
||||
ezRemote Client is an application that allows you to connect the PS4 to remote FTP/SFTP, SMB, NFS, WebDAV, HTTP servers and Google Drive to transfer files. The interface is inspired by Filezilla client which provides a commander like GUI.
|
||||

|
||||
|
||||
**New:** As of version 1.0.8, ezRemote Client has a Web Interface that can be access from any modern browser to manage the PS4 files.
|
||||
**New:** As of version 1.0.9. Remote Package Installation does not require you to host an external Http Server. The embedded Web Server built into ezRemote Client acts as a Proxy Server between the PS4 and remote server (FTP, SFTP, SMB, NFS, WebDev, Google Drive). There's no data written to the PS4 hard drive in the process, rather everything is streamed via embedded Web Server directly to the PS4 installer.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Usage
|
||||
|
||||
@@ -112,8 +112,8 @@ STR_CANNOT_CONNECT_REMOTE_MSG=Remote HTTP Server not reachable.
|
||||
STR_DOWNLOAD_INSTALL_MSG=Remote Package Install not possible. Would you like to download package and install instead?
|
||||
STR_CHECKING_REMOTE_SERVER_MSG=Checking remote server for Remote Package Install.
|
||||
STR_ENABLE_RPI=RPI
|
||||
STR_ENABLE_RPI_FTP_SMB_MSG=This option enables Remote Package Installation. This requires a HTTP Server setup on the same host sharing the same folder with anonymous access.
|
||||
STR_ENABLE_RPI_WEBDAV_MSG=This option enables Remote Package Installation. This requires the Server with anonymous access that does not need username/password.
|
||||
STR_ENABLE_RPI_FTP_SMB_MSG=This option enables Remote Package Installation via embedded Web Server.
|
||||
STR_ENABLE_RPI_WEBDAV_MSG==This option enables Remote Package Installation via embedded Web Server.
|
||||
STR_FILES=Files
|
||||
STR_EDITOR=Editor
|
||||
STR_SAVE=Save
|
||||
|
||||
@@ -112,8 +112,8 @@ STR_CANNOT_CONNECT_REMOTE_MSG=Servidor HTTP remoto não esta acessível.
|
||||
STR_DOWNLOAD_INSTALL_MSG=A instalação remota do pacote não é possível. Você gostaria de baixar o pacote e instalar?
|
||||
STR_CHECKING_REMOTE_SERVER_MSG=Verificando servidor remoto para instalação de pacote remoto.
|
||||
STR_ENABLE_RPI=RPI
|
||||
STR_ENABLE_RPI_FTP_SMB_MSG=Esta opção permite a instalação remota de pacotes. Isso requer uma configuração de servidor HTTP no mesmo Host compartilhando a mesma pasta com acesso anônimo.
|
||||
STR_ENABLE_RPI_WEBDAV_MSG=Esta opção permite a instalação remota de pacotes. Isso requer o servidor com acesso anônimo que não precisa de nome de usuário/senha.
|
||||
STR_ENABLE_RPI_FTP_SMB_MSG=Esta opção permite a instalação remota de pacotes.
|
||||
STR_ENABLE_RPI_WEBDAV_MSG=Esta opção permite a instalação remota de pacotes.
|
||||
STR_FILES=Arquivos
|
||||
STR_EDITOR=Editar
|
||||
STR_SAVE=Salvar
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <minizip/unzip.h>
|
||||
#include <orbis/SystemService.h>
|
||||
#include "clients/gdrive.h"
|
||||
#include "clients/ftpclient.h"
|
||||
#include "clients/smbclient.h"
|
||||
@@ -365,6 +366,7 @@ namespace Actions
|
||||
return remoteclient->Put(src, dest);
|
||||
}
|
||||
|
||||
sceSystemServicePowerTick();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -516,6 +518,7 @@ namespace Actions
|
||||
return remoteclient->Get(dest, src);
|
||||
}
|
||||
|
||||
sceSystemServicePowerTick();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -672,6 +675,7 @@ namespace Actions
|
||||
{
|
||||
download_and_install = true;
|
||||
}
|
||||
|
||||
for (std::vector<DirEntry>::iterator it = files.begin(); it != files.end(); ++it)
|
||||
{
|
||||
if (stop_activity)
|
||||
|
||||
@@ -94,6 +94,29 @@ int BaseClient::Get(const std::string &outputfile, const std::string &path, uint
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BaseClient::GetRange(const std::string &path, DataSink &sink, 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;
|
||||
if (auto res = client->Get(GetFullPath(path), headers,
|
||||
[&](const char *data, size_t data_length)
|
||||
{
|
||||
bytes_read += data_length;
|
||||
bool ok = sink.write(data, data_length);
|
||||
return ok;
|
||||
}))
|
||||
{
|
||||
return bytes_read == size;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(this->response, "%s", httplib::to_string(res.error()).c_str());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BaseClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset)
|
||||
{
|
||||
char range_header[64];
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <vector>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "http/httplib.h"
|
||||
#include "common.h"
|
||||
|
||||
class BaseClient : public RemoteClient
|
||||
@@ -18,6 +19,7 @@ public:
|
||||
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 GetRange(const std::string &path, DataSink &sink, 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);
|
||||
|
||||
@@ -1266,6 +1266,43 @@ 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, DataSink &sink, 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[FTP_CLIENT_BUFSIZ];
|
||||
int count = 0;
|
||||
size_t bytes_remaining = size;
|
||||
|
||||
do
|
||||
{
|
||||
size_t bytes_to_read = std::min<size_t>(FTP_CLIENT_BUFSIZ, bytes_remaining);
|
||||
count = FtpRead(buf, bytes_to_read, nData);
|
||||
if (count > 0)
|
||||
{
|
||||
bytes_remaining -= count;
|
||||
bool ok = sink.write((char*)buf, count);
|
||||
if (!ok)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
FtpClose(nData);
|
||||
mp_ftphandle->offset = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FtpClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset)
|
||||
{
|
||||
ftphandle *nData;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "clients/remote_client.h"
|
||||
#include "http/httplib.h"
|
||||
|
||||
#define FTP_CLIENT_MAX_FILENAME_LEN 128
|
||||
|
||||
@@ -79,6 +80,7 @@ public:
|
||||
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 GetRange(const std::string &path, DataSink &sink, 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);
|
||||
|
||||
@@ -331,6 +331,35 @@ int GDriveClient::Get(const std::string &outputfile, const std::string &path, ui
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GDriveClient::GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset)
|
||||
{
|
||||
size_t bytes_read = 0;
|
||||
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)
|
||||
{
|
||||
bytes_read += data_length;
|
||||
bool ok = sink.write(data, data_length);
|
||||
return ok;
|
||||
}))
|
||||
{
|
||||
return bytes_read == size;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(this->response, "%s", httplib::to_string(res.error()).c_str());
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int GDriveClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset)
|
||||
{
|
||||
size_t bytes_read = 0;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "http/httplib.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/baseclient.h"
|
||||
#include "http/httplib.h"
|
||||
#include "common.h"
|
||||
|
||||
static pthread_t refresh_token_thid;
|
||||
@@ -20,6 +21,7 @@ public:
|
||||
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 GetRange(const std::string &path, DataSink &sink, 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);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "util.h"
|
||||
#include "system.h"
|
||||
|
||||
#define BUF_SIZE 64*1024
|
||||
#define BUF_SIZE 256*1024
|
||||
|
||||
NfsClient::NfsClient()
|
||||
{
|
||||
@@ -233,6 +233,49 @@ int NfsClient::Get(const std::string &outputfile, const std::string &ppath, uint
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NfsClient::GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset)
|
||||
{
|
||||
struct nfsfh *nfsfh = nullptr;
|
||||
int ret = nfs_open(nfs, path.c_str(), 0400, &nfsfh);
|
||||
if (ret != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = nfs_lseek(nfs, nfsfh, offset, SEEK_SET, NULL);
|
||||
if (ret != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *buff = malloc(BUF_SIZE);
|
||||
int count = 0;
|
||||
size_t bytes_remaining = size;
|
||||
do
|
||||
{
|
||||
size_t bytes_to_read = std::min<size_t>(BUF_SIZE, bytes_remaining);
|
||||
count = nfs_read(nfs, nfsfh, bytes_to_read, buff);
|
||||
if (count > 0)
|
||||
{
|
||||
bytes_remaining -= count;
|
||||
bool ok = sink.write((char*)buff, count);
|
||||
if (!ok)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
free((void *)buff);
|
||||
nfs_close(nfs, nfsfh);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NfsClient::GetRange(const std::string &ppath, void *buffer, uint64_t size, uint64_t offset)
|
||||
{
|
||||
if (!FileExists(ppath))
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "nfsc/libnfs-raw.h"
|
||||
#include "nfsc/libnfs-raw-mount.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "http/httplib.h"
|
||||
#include "common.h"
|
||||
|
||||
class NfsClient : public RemoteClient
|
||||
@@ -23,6 +24,7 @@ public:
|
||||
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 GetRange(const std::string &path, DataSink &sink, 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);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "common.h"
|
||||
#include "http/httplib.h"
|
||||
|
||||
enum RemoteActions
|
||||
{
|
||||
@@ -25,6 +26,7 @@ enum RemoteActions
|
||||
enum ClientType
|
||||
{
|
||||
CLIENT_TYPE_FTP,
|
||||
CLIENT_TYPE_SFTP,
|
||||
CLIENT_TYPE_SMB,
|
||||
CLIENT_TYPE_WEBDAV,
|
||||
CLIENT_TYPE_HTTP_SERVER,
|
||||
@@ -33,6 +35,8 @@ enum ClientType
|
||||
CLINET_TYPE_UNKNOWN
|
||||
};
|
||||
|
||||
using namespace httplib;
|
||||
|
||||
class RemoteClient
|
||||
{
|
||||
public:
|
||||
@@ -50,6 +54,7 @@ public:
|
||||
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 int GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset) = 0;
|
||||
virtual bool FileExists(const std::string &path) = 0;
|
||||
virtual std::vector<DirEntry> ListDir(const std::string &path) = 0;
|
||||
virtual std::string GetPath(std::string path1, std::string path2) = 0;
|
||||
|
||||
@@ -255,6 +255,7 @@ int SFTPClient::Size(const std::string &path, int64_t *size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*size = attrs.filesize;
|
||||
return 1;
|
||||
}
|
||||
@@ -296,12 +297,48 @@ int SFTPClient::Get(const std::string &outputfile, const std::string &path, uint
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
free((char *)buff);
|
||||
FS::Close(out);
|
||||
libssh2_sftp_close(sftp_handle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SFTPClient::GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset)
|
||||
{
|
||||
LIBSSH2_SFTP_HANDLE *sftp_handle = libssh2_sftp_open(sftp_session, path.c_str(), LIBSSH2_FXF_READ, 0);
|
||||
if (!sftp_handle)
|
||||
{
|
||||
sprintf(response, "Unable to open file with SFTP: %ld", libssh2_sftp_last_error(sftp_session));
|
||||
return 0;
|
||||
}
|
||||
|
||||
libssh2_sftp_seek64(sftp_handle, offset);
|
||||
|
||||
char *buff = (char *)malloc(FTP_CLIENT_BUFSIZ);
|
||||
int rc, count = 0;
|
||||
size_t bytes_remaining = size;
|
||||
do
|
||||
{
|
||||
size_t bytes_to_read = std::min<size_t>(FTP_CLIENT_BUFSIZ, bytes_remaining);
|
||||
rc = libssh2_sftp_read(sftp_handle, buff, bytes_to_read);
|
||||
if (rc > 0)
|
||||
{
|
||||
bytes_remaining -= rc;
|
||||
sink.write(buff, rc);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
free((char *)buff);
|
||||
libssh2_sftp_close(sftp_handle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SFTPClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset)
|
||||
{
|
||||
int64_t filesize;
|
||||
@@ -601,7 +638,7 @@ int SFTPClient::Quit()
|
||||
|
||||
ClientType SFTPClient::clientType()
|
||||
{
|
||||
return CLIENT_TYPE_FTP;
|
||||
return CLIENT_TYPE_SFTP;
|
||||
}
|
||||
|
||||
uint32_t SFTPClient::SupportedActions()
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "clients/remote_client.h"
|
||||
#include "http/httplib.h"
|
||||
#include "common.h"
|
||||
|
||||
class SFTPClient : public RemoteClient
|
||||
@@ -20,6 +21,7 @@ public:
|
||||
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 GetRange(const std::string &path, DataSink &sink, 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);
|
||||
|
||||
@@ -226,6 +226,46 @@ int SmbClient::Get(const std::string &outputfile, const std::string &ppath, uint
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SmbClient::GetRange(const std::string &ppath, DataSink &sink, uint64_t size, uint64_t offset)
|
||||
{
|
||||
std::string path = std::string(ppath);
|
||||
path = Util::Trim(path, "/");
|
||||
struct smb2fh* in = smb2_open(smb2, path.c_str(), O_RDONLY);
|
||||
if (in == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
smb2_lseek(smb2, in, offset, SEEK_SET, NULL);
|
||||
|
||||
uint8_t *buff = (uint8_t*)malloc(max_read_size);
|
||||
int count = 0;
|
||||
size_t bytes_remaining = size;
|
||||
do
|
||||
{
|
||||
size_t bytes_to_read = std::min<size_t>(max_read_size, bytes_remaining);
|
||||
count = smb2_read(smb2, in, buff, bytes_to_read);
|
||||
if (count > 0)
|
||||
{
|
||||
bytes_remaining -= count;
|
||||
bool ok = sink.write((char*)buff, count);
|
||||
if (!ok)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
free((char *)buff);
|
||||
smb2_close(smb2, in);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SmbClient::GetRange(const std::string &ppath, void *buffer, uint64_t size, uint64_t offset)
|
||||
{
|
||||
std::string path = std::string(ppath);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <vector>
|
||||
#include <smb2/smb2.h>
|
||||
#include <smb2/libsmb2.h>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "common.h"
|
||||
|
||||
@@ -24,6 +25,7 @@ public:
|
||||
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 GetRange(const std::string &path, DataSink &sink, 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);
|
||||
|
||||
@@ -215,6 +215,11 @@ namespace WebDAV
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WebDavClient::GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset)
|
||||
{
|
||||
return client->download_range_to(path, sink, offset, offset+size-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Put - issue a PUT command and send data from input
|
||||
*
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <regex>
|
||||
#include "http/httplib.h"
|
||||
#include "webdav/client.hpp"
|
||||
#include "clients/remote_client.h"
|
||||
#include "common.h"
|
||||
|
||||
using namespace httplib;
|
||||
|
||||
namespace WebDAV
|
||||
{
|
||||
inline std::string GetHttpUrl(std::string url)
|
||||
@@ -29,6 +32,7 @@ namespace WebDAV
|
||||
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 GetRange(const std::string &path, DataSink &sink, 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);
|
||||
|
||||
+6
-6
@@ -82,10 +82,14 @@ namespace CONFIG
|
||||
{
|
||||
setting->type = CLIENT_TYPE_SMB;
|
||||
}
|
||||
else if (strncmp(setting->server, "ftp://", 6) == 0 || strncmp(setting->server, "sftp://", 7) == 0)
|
||||
else if (strncmp(setting->server, "ftp://", 6) == 0)
|
||||
{
|
||||
setting->type = CLIENT_TYPE_FTP;
|
||||
}
|
||||
else if (strncmp(setting->server, "sftp://", 7) == 0)
|
||||
{
|
||||
setting->type = CLIENT_TYPE_SFTP;
|
||||
}
|
||||
else if (strncmp(setting->server, "webdav://", 9) == 0 || strncmp(setting->server, "webdavs://", 10) == 0)
|
||||
{
|
||||
setting->type = CLIENT_TYPE_WEBDAV;
|
||||
@@ -244,10 +248,7 @@ namespace CONFIG
|
||||
}
|
||||
WriteString(sites[i].c_str(), CONFIG_REMOTE_SERVER_PASSWORD, encrypted_password.c_str());
|
||||
|
||||
setting.http_port = ReadInt(sites[i].c_str(), CONFIG_REMOTE_SERVER_HTTP_PORT, 80);
|
||||
WriteInt(sites[i].c_str(), CONFIG_REMOTE_SERVER_HTTP_PORT, setting.http_port);
|
||||
|
||||
setting.enable_rpi = ReadBool(sites[i].c_str(), CONFIG_ENABLE_RPI, false);
|
||||
setting.enable_rpi = ReadBool(sites[i].c_str(), CONFIG_ENABLE_RPI, true);
|
||||
WriteBool(sites[i].c_str(), CONFIG_ENABLE_RPI, setting.enable_rpi);
|
||||
|
||||
sprintf(setting.http_server_type, "%s", ReadString(sites[i].c_str(), CONFIG_REMOTE_HTTP_SERVER_TYPE, HTTP_SERVER_APACHE));
|
||||
@@ -322,7 +323,6 @@ namespace CONFIG
|
||||
WriteString(last_site, CONFIG_REMOTE_SERVER_URL, remote_settings->server);
|
||||
WriteString(last_site, CONFIG_REMOTE_SERVER_USER, remote_settings->username);
|
||||
WriteString(last_site, CONFIG_REMOTE_SERVER_PASSWORD, encrypted_text.c_str());
|
||||
WriteInt(last_site, CONFIG_REMOTE_SERVER_HTTP_PORT, remote_settings->http_port);
|
||||
WriteBool(last_site, CONFIG_ENABLE_RPI, remote_settings->enable_rpi);
|
||||
WriteString(last_site, CONFIG_REMOTE_HTTP_SERVER_TYPE, remote_settings->http_server_type);
|
||||
WriteString(last_site, CONFIG_REMOTE_DEFAULT_DIRECTORY, remote_settings->default_directory);
|
||||
|
||||
@@ -98,7 +98,6 @@ struct RemoteSettings
|
||||
char server[256];
|
||||
char username[33];
|
||||
char password[128];
|
||||
int http_port;
|
||||
ClientType type;
|
||||
bool enable_rpi;
|
||||
uint32_t supported_actions;
|
||||
|
||||
@@ -353,7 +353,7 @@ private:
|
||||
|
||||
} // namespace detail
|
||||
|
||||
using Headers = std::multimap<std::string, std::string, detail::ci>;
|
||||
using Headers = std::map<std::string, std::string, detail::ci>;
|
||||
|
||||
using Params = std::multimap<std::string, std::string>;
|
||||
using Match = std::smatch;
|
||||
|
||||
+72
-88
@@ -9,9 +9,11 @@
|
||||
#include <orbis/Bgft.h>
|
||||
#include <orbis/AppInstUtil.h>
|
||||
#include <orbis/UserService.h>
|
||||
#include <orbis/SystemService.h>
|
||||
#include <curl/curl.h>
|
||||
#include <web/request.hpp>
|
||||
#include <web/urn.hpp>
|
||||
#include "server/http_server.h"
|
||||
#include "installer.h"
|
||||
#include "util.h"
|
||||
#include "config.h"
|
||||
@@ -97,11 +99,12 @@ namespace INSTALLER
|
||||
s_bgft_initialized = false;
|
||||
}
|
||||
|
||||
std::string getRemoteUrl(const std::string filename, bool encodeUrl)
|
||||
std::string getRemoteUrl(const std::string path, bool encodeUrl)
|
||||
{
|
||||
if (remoteclient->clientType() == CLIENT_TYPE_WEBDAV || remoteclient->clientType() == CLIENT_TYPE_HTTP_SERVER)
|
||||
if (strlen(remote_settings->username) == 0 && strlen(remote_settings->password) == 0 &&
|
||||
(remoteclient->clientType() == CLIENT_TYPE_WEBDAV || remoteclient->clientType() == CLIENT_TYPE_HTTP_SERVER))
|
||||
{
|
||||
std::string full_url = WebDAV::GetHttpUrl(remote_settings->server + filename);
|
||||
std::string full_url = WebDAV::GetHttpUrl(remote_settings->server + path);
|
||||
size_t scheme_pos = full_url.find("://");
|
||||
if (scheme_pos == std::string::npos)
|
||||
return "";
|
||||
@@ -121,24 +124,14 @@ namespace INSTALLER
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string full_url = std::string(remote_settings->server);
|
||||
size_t scheme_pos = full_url.find("://");
|
||||
if (scheme_pos == std::string::npos)
|
||||
return "";
|
||||
size_t root_pos = full_url.find("/", scheme_pos + 3);
|
||||
std::string host = full_url.substr(scheme_pos + 3, (root_pos - (scheme_pos + 3)));
|
||||
size_t port_pos = host.find(":");
|
||||
if (port_pos != std::string::npos)
|
||||
host = host.substr(0, port_pos);
|
||||
std::string encoded_path = path;
|
||||
Web::Urn::Path uri(encoded_path);
|
||||
CURL *curl = curl_easy_init();
|
||||
encoded_path = uri.quote(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
std::string full_url = std::string("http://localhost:") + std::to_string(http_server_port) + "/rmt_inst" + encoded_path;
|
||||
|
||||
std::string path = std::string(filename);
|
||||
if (encodeUrl)
|
||||
{
|
||||
Web::Urn::Path uri(path);
|
||||
CURL *curl = curl_easy_init();
|
||||
path = uri.quote(curl);
|
||||
}
|
||||
return "http://" + host + ":" + std::to_string(remote_settings->http_port) + path;
|
||||
return full_url;
|
||||
}
|
||||
|
||||
return "";
|
||||
@@ -146,45 +139,18 @@ namespace INSTALLER
|
||||
|
||||
bool canInstallRemotePkg(const std::string &url)
|
||||
{
|
||||
if (remoteclient->clientType() == CLIENT_TYPE_WEBDAV)
|
||||
{
|
||||
if (strlen(remote_settings->username) > 0)
|
||||
{
|
||||
sprintf(confirm_message, "%s %s", lang_strings[STR_REMOTE_NOT_SUPPORT_MSG], lang_strings[STR_DOWNLOAD_INSTALL_MSG]);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t scheme_pos = url.find_first_of("://");
|
||||
size_t path_pos = url.find_first_of("/", scheme_pos + 3);
|
||||
std::string host = url.substr(0, path_pos);
|
||||
std::string path = url.substr(path_pos);
|
||||
|
||||
WebDAV::WebDavClient tmp_client;
|
||||
tmp_client.Connect(host.c_str(), "", "", false);
|
||||
WebDAV::dict_t response_headers{};
|
||||
int ret = tmp_client.GetHeaders(path.c_str(), &response_headers);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
sprintf(confirm_message, "%s %s", lang_strings[STR_CANNOT_CONNECT_REMOTE_MSG], lang_strings[STR_DOWNLOAD_INSTALL_MSG]);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int InstallRemotePkg(const std::string &filename, pkg_header *header)
|
||||
int InstallRemotePkg(const std::string &path, pkg_header *header)
|
||||
{
|
||||
std::string url = getRemoteUrl(filename, true);
|
||||
std::string url = getRemoteUrl(path, true);
|
||||
|
||||
if (url.empty())
|
||||
return 0;
|
||||
|
||||
int ret;
|
||||
std::string filename = path.substr(path.find_last_of("/")+1);
|
||||
std::string cid = std::string((char *)header->pkg_content_id);
|
||||
cid = cid.substr(cid.find_first_of("-") + 1, 9);
|
||||
int user_id;
|
||||
@@ -222,6 +188,7 @@ namespace INSTALLER
|
||||
is_patch = true;
|
||||
}
|
||||
|
||||
OrbisBgftTaskProgress progress_info;
|
||||
OrbisBgftDownloadParam params;
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
{
|
||||
@@ -229,7 +196,7 @@ namespace INSTALLER
|
||||
params.entitlementType = 5;
|
||||
params.id = (char *)header->pkg_content_id;
|
||||
params.contentUrl = url.c_str();
|
||||
params.contentName = cid.c_str();
|
||||
params.contentName = filename.c_str();
|
||||
params.iconPath = "";
|
||||
params.playgoScenarioId = "0";
|
||||
params.option = ORBIS_BGFT_TASK_OPT_DISABLE_CDN_QUERY_PARAM;
|
||||
@@ -246,7 +213,7 @@ namespace INSTALLER
|
||||
ret = sceBgftServiceIntDebugDownloadRegisterPkg(¶ms, &task_id);
|
||||
if (ret == 0x80990088 || ret == 0x80990015)
|
||||
{
|
||||
sprintf(confirm_message, "%s - %s?", filename.c_str(), lang_strings[STR_REINSTALL_CONFIRM_MSG]);
|
||||
sprintf(confirm_message, "%s - %s?", path.c_str(), lang_strings[STR_REINSTALL_CONFIRM_MSG]);
|
||||
confirm_state = CONFIRM_WAIT;
|
||||
action_to_take = selected_action;
|
||||
activity_inprogess = false;
|
||||
@@ -274,47 +241,59 @@ namespace INSTALLER
|
||||
goto err;
|
||||
}
|
||||
|
||||
Util::Notify("%s queued", cid.c_str());
|
||||
return 1;
|
||||
Util::Notify("%s queued", filename.c_str());
|
||||
|
||||
file_transfering = true;
|
||||
bytes_to_download = 100;
|
||||
bytes_transfered = 0;
|
||||
while (bytes_transfered < 99)
|
||||
{
|
||||
memset(&progress_info, 0, sizeof(progress_info));
|
||||
ret = sceBgftServiceDownloadGetProgress(task_id, &progress_info);
|
||||
if (ret || (progress_info.transferred > 0 && progress_info.errorResult != 0))
|
||||
return 0;
|
||||
bytes_transfered = (uint32_t)(((float)progress_info.transferred / progress_info.length) * 100.f);
|
||||
sceSystemServicePowerTick();
|
||||
}
|
||||
|
||||
return 1;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int InstallLocalPkg(const std::string &filename)
|
||||
int InstallLocalPkg(const std::string &path)
|
||||
{
|
||||
int ret;
|
||||
pkg_header header;
|
||||
memset(&header, 0, sizeof(header));
|
||||
if (FS::Head(filename.c_str(), (void *)&header, sizeof(header)) == 0)
|
||||
if (FS::Head(path.c_str(), (void *)&header, sizeof(header)) == 0)
|
||||
return 0;
|
||||
|
||||
if (BE32(header.pkg_magic) != PKG_MAGIC)
|
||||
return 0;
|
||||
|
||||
char filepath[1024];
|
||||
snprintf(filepath, 1023, "%s", filename.c_str());
|
||||
if (strncmp(filename.c_str(), "/data/", 6) == 0)
|
||||
snprintf(filepath, 1023, "/user%s", filename.c_str());
|
||||
snprintf(filepath, 1023, "%s", path.c_str());
|
||||
if (strncmp(path.c_str(), "/data/", 6) == 0)
|
||||
snprintf(filepath, 1023, "/user%s", path.c_str());
|
||||
|
||||
char titleId[18];
|
||||
memset(titleId, 0, sizeof(titleId));
|
||||
int is_app = -1;
|
||||
ret = sceAppInstUtilGetTitleIdFromPkg(filename.c_str(), titleId, &is_app);
|
||||
ret = sceAppInstUtilGetTitleIdFromPkg(path.c_str(), titleId, &is_app);
|
||||
if (ret)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
OrbisBgftTaskProgress progress_info;
|
||||
int prog = 0;
|
||||
OrbisBgftDownloadParamEx download_params;
|
||||
memset(&download_params, 0, sizeof(download_params));
|
||||
{
|
||||
download_params.params.entitlementType = 5;
|
||||
download_params.params.id = (char *)header.pkg_content_id;
|
||||
download_params.params.contentUrl = filepath;
|
||||
download_params.params.contentName = (char *)header.pkg_content_id;
|
||||
download_params.params.contentName = path.c_str();
|
||||
;
|
||||
download_params.params.iconPath = "";
|
||||
download_params.params.playgoScenarioId = "0";
|
||||
@@ -339,15 +318,19 @@ namespace INSTALLER
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
Util::Notify("%s queued", titleId);
|
||||
Util::Notify("%s queued", path.c_str());
|
||||
|
||||
while (prog < 99)
|
||||
file_transfering = true;
|
||||
bytes_to_download = 100;
|
||||
bytes_transfered = 0;
|
||||
while (bytes_transfered < 99)
|
||||
{
|
||||
memset(&progress_info, 0, sizeof(progress_info));
|
||||
ret = sceBgftServiceDownloadGetProgress(task_id, &progress_info);
|
||||
if (ret || (progress_info.transferred > 0 && progress_info.errorResult != 0))
|
||||
return 0;
|
||||
prog = (uint32_t)(((float)progress_info.transferred / progress_info.length) * 100.f);
|
||||
bytes_transfered = (uint32_t)(((float)progress_info.transferred / progress_info.length) * 100.f);
|
||||
sceSystemServicePowerTick();
|
||||
}
|
||||
return 1;
|
||||
|
||||
@@ -355,22 +338,23 @@ namespace INSTALLER
|
||||
return 0;
|
||||
}
|
||||
|
||||
int InstallLocalPkg(const std::string &filename, pkg_header *header, bool remove_after_install)
|
||||
int InstallLocalPkg(const std::string &path, pkg_header *header, bool remove_after_install)
|
||||
{
|
||||
int ret;
|
||||
if (strncmp(filename.c_str(), "/data/", 6) != 0 &&
|
||||
strncmp(filename.c_str(), "/user/data/", 11) != 0 &&
|
||||
strncmp(filename.c_str(), "/mnt/usb", 8) != 0)
|
||||
if (strncmp(path.c_str(), "/data/", 6) != 0 &&
|
||||
strncmp(path.c_str(), "/user/data/", 11) != 0 &&
|
||||
strncmp(path.c_str(), "/mnt/usb", 8) != 0)
|
||||
return -1;
|
||||
|
||||
std::string filename = path.substr(path.find_last_of("/")+1);
|
||||
char filepath[1024];
|
||||
snprintf(filepath, 1023, "%s", filename.c_str());
|
||||
if (strncmp(filename.c_str(), "/data/", 6) == 0)
|
||||
snprintf(filepath, 1023, "/user%s", filename.c_str());
|
||||
snprintf(filepath, 1023, "%s", path.c_str());
|
||||
if (strncmp(path.c_str(), "/data/", 6) == 0)
|
||||
snprintf(filepath, 1023, "/user%s", path.c_str());
|
||||
char titleId[18];
|
||||
memset(titleId, 0, sizeof(titleId));
|
||||
int is_app = -1;
|
||||
ret = sceAppInstUtilGetTitleIdFromPkg(filename.c_str(), titleId, &is_app);
|
||||
ret = sceAppInstUtilGetTitleIdFromPkg(path.c_str(), titleId, &is_app);
|
||||
if (ret)
|
||||
{
|
||||
return 0;
|
||||
@@ -384,7 +368,7 @@ namespace INSTALLER
|
||||
download_params.params.entitlementType = 5;
|
||||
download_params.params.id = (char *)header->pkg_content_id;
|
||||
download_params.params.contentUrl = filepath;
|
||||
download_params.params.contentName = (char *)header->pkg_content_id;
|
||||
download_params.params.contentName = filename.c_str();
|
||||
;
|
||||
download_params.params.iconPath = "";
|
||||
download_params.params.playgoScenarioId = "0";
|
||||
@@ -397,7 +381,7 @@ namespace INSTALLER
|
||||
ret = sceBgftServiceIntDownloadRegisterTaskByStorageEx(&download_params, &task_id);
|
||||
if (ret == 0x80990088 || ret == 0x80990015)
|
||||
{
|
||||
sprintf(confirm_message, "%s - %s?", filename.c_str(), lang_strings[STR_REINSTALL_CONFIRM_MSG]);
|
||||
sprintf(confirm_message, "%s - %s?", path.c_str(), lang_strings[STR_REINSTALL_CONFIRM_MSG]);
|
||||
confirm_state = CONFIRM_WAIT;
|
||||
action_to_take = selected_action;
|
||||
activity_inprogess = false;
|
||||
@@ -418,7 +402,7 @@ namespace INSTALLER
|
||||
else
|
||||
{
|
||||
if (auto_delete_tmp_pkg)
|
||||
FS::Rm(filename);
|
||||
FS::Rm(path);
|
||||
}
|
||||
}
|
||||
else if (ret > 0)
|
||||
@@ -432,7 +416,7 @@ namespace INSTALLER
|
||||
|
||||
if (!remove_after_install)
|
||||
{
|
||||
Util::Notify("%s queued", titleId);
|
||||
Util::Notify("%s queued", filename.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -450,24 +434,24 @@ namespace INSTALLER
|
||||
bytes_transfered = progress_info.transferred;
|
||||
}
|
||||
if (auto_delete_tmp_pkg)
|
||||
FS::Rm(filename);
|
||||
FS::Rm(path);
|
||||
return 1;
|
||||
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ExtractLocalPkg(const std::string &filename, const std::string sfo_path, const std::string icon_path)
|
||||
bool ExtractLocalPkg(const std::string &path, const std::string sfo_path, const std::string icon_path)
|
||||
{
|
||||
pkg_header tmp_hdr;
|
||||
FS::Head(filename, &tmp_hdr, sizeof(pkg_header));
|
||||
FS::Head(path, &tmp_hdr, sizeof(pkg_header));
|
||||
|
||||
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);
|
||||
|
||||
FILE *fd = FS::OpenRead(filename);
|
||||
FILE *fd = FS::OpenRead(path);
|
||||
FS::Seek(fd, entry_table_offset);
|
||||
FS::Read(fd, entry_table_data, entry_table_size);
|
||||
|
||||
@@ -528,10 +512,10 @@ namespace INSTALLER
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExtractRemotePkg(const std::string &filename, const std::string sfo_path, const std::string icon_path)
|
||||
bool ExtractRemotePkg(const std::string &path, const std::string sfo_path, const std::string icon_path)
|
||||
{
|
||||
pkg_header tmp_hdr;
|
||||
if (!remoteclient->Head(filename, &tmp_hdr, sizeof(pkg_header)))
|
||||
if (!remoteclient->Head(path, &tmp_hdr, sizeof(pkg_header)))
|
||||
return false;
|
||||
|
||||
size_t entry_count = BE32(tmp_hdr.pkg_entry_count);
|
||||
@@ -539,7 +523,7 @@ namespace INSTALLER
|
||||
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))
|
||||
if (!remoteclient->GetRange(path, entry_table_data, entry_table_size, entry_table_offset))
|
||||
return false;
|
||||
|
||||
pkg_table_entry *entries = (pkg_table_entry *)entry_table_data;
|
||||
@@ -577,7 +561,7 @@ namespace INSTALLER
|
||||
{
|
||||
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))
|
||||
if (!remoteclient->GetRange(path, param_sfo_data, param_sfo_size, param_sfo_offset))
|
||||
{
|
||||
FS::Close(out);
|
||||
return false;
|
||||
@@ -591,7 +575,7 @@ namespace INSTALLER
|
||||
{
|
||||
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))
|
||||
if (!remoteclient->GetRange(path, icon0_png_data, icon0_png_size, icon0_png_offset))
|
||||
{
|
||||
FS::Close(out);
|
||||
return false;
|
||||
|
||||
+6
-6
@@ -120,10 +120,10 @@ namespace INSTALLER
|
||||
void Exit(void);
|
||||
|
||||
bool canInstallRemotePkg(const std::string &url);
|
||||
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);
|
||||
int InstallLocalPkg(const std::string &filename, pkg_header *header, bool remove_after_install = false);
|
||||
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);
|
||||
std::string getRemoteUrl(const std::string path, bool encodeUrl = false);
|
||||
int InstallRemotePkg(const std::string &path, pkg_header *header);
|
||||
int InstallLocalPkg(const std::string &path);
|
||||
int InstallLocalPkg(const std::string &path, pkg_header *header, bool remove_after_install = false);
|
||||
bool ExtractLocalPkg(const std::string &path, const std::string sfo_path, const std::string icon_path);
|
||||
bool ExtractRemotePkg(const std::string &path, const std::string sfo_path, const std::string icon_path);
|
||||
}
|
||||
+116
-118
@@ -10,124 +10,122 @@ char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE] = {
|
||||
|
||||
// This is properly populated so that emulator won't crash if an user launches it without language INI files.
|
||||
char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE] = {
|
||||
"Connection Settings", // STR_CONNECTION_SETTINGS
|
||||
"Site", // STR_SITE
|
||||
"Local", // STR_LOCAL
|
||||
"Remote", // STR_REMOTE
|
||||
"Messages", // STR_MESSAGES
|
||||
"Update Software", // STR_UPDATE_SOFTWARE
|
||||
"Connect", // STR_CONNECT
|
||||
"Disconnect", // STR_DISCONNECT
|
||||
"Search", // STR_SEARCH
|
||||
"Refresh", // STR_REFRESH
|
||||
"Server", // STR_SERVER
|
||||
"Username", // STR_USERNAME
|
||||
"Password", // STR_PASSWORD
|
||||
"Port", // STR_PORT
|
||||
"Pasv", // STR_PASV
|
||||
"Directory", // STR_DIRECTORY
|
||||
"Filter", // STR_FILTER
|
||||
"Yes", // STR_YES
|
||||
"No", // STR_NO
|
||||
"Cancel", // STR_CANCEL
|
||||
"Continue", // STR_CONTINUE
|
||||
"Close", // STR_CLOSE
|
||||
"Folder", // STR_FOLDER
|
||||
"File", // STR_FILE
|
||||
"Type", // STR_TYPE
|
||||
"Name", // STR_NAME
|
||||
"Size", // STR_SIZE
|
||||
"Date", // STR_DATE
|
||||
"New Folder", // STR_NEW_FOLDER
|
||||
"Rename", // STR_RENAME
|
||||
"Delete", // STR_DELETE
|
||||
"Upload", // STR_UPLOAD
|
||||
"Download", // STR_DOWNLOAD
|
||||
"Select All", // STR_SELECT_ALL
|
||||
"Clear All", // STR_CLEAR_ALL
|
||||
"Uploading", // STR_UPLOADING
|
||||
"Downloading", // STR_DOWNLOADING
|
||||
"Overwrite", // STR_OVERWRITE
|
||||
"Don't Overwrite", // STR_DONT_OVERWRITE
|
||||
"Ask for Confirmation", // STR_ASK_FOR_CONFIRM
|
||||
"Don't Ask for Confirmation", // STR_DONT_ASK_CONFIRM
|
||||
"Always use this option and don't ask again", // STR_ALLWAYS_USE_OPTION
|
||||
"Actions", // STR_ACTIONS
|
||||
"Confirm", // STR_CONFIRM
|
||||
"Overwrite Options", // STR_OVERWRITE_OPTIONS
|
||||
"Properties", // STR_PROPERTIES
|
||||
"Progress", // STR_PROGRESS
|
||||
"Updates", // STR_UPDATES
|
||||
"Are you sure you want to delete this file(s)/folder(s)?", // STR_DEL_CONFIRM_MSG
|
||||
"Canceling. Waiting for last action to complete", // STR_CANCEL_ACTION_MSG
|
||||
"Failed to upload file", // STR_FAIL_UPLOAD_MSG
|
||||
"Failed to download file", // STR_FAIL_DOWNLOAD_MSG
|
||||
"Failed to read contents of directory or folder does not exist.", // STR_FAIL_READ_LOCAL_DIR_MSG
|
||||
"426 Connection closed.", // STR_CONNECTION_CLOSE_ERR_MSG
|
||||
"426 Remote Server has terminated the connection.", // STR_REMOTE_TERM_CONN_MSG
|
||||
"300 Failed Login. Please check your username or password.", // STR_FAIL_LOGIN_MSG
|
||||
"426 Failed. Connection timeout.", // STR_FAIL_TIMEOUT_MSG
|
||||
"Failed to delete directory", // STR_FAIL_DEL_DIR_MSG
|
||||
"Deleting", // STR_DELETING
|
||||
"Failed to delete file", // STR_FAIL_DEL_FILE_MSG
|
||||
"Deleted", // STR_DELETED
|
||||
"Link", // STR_LINK
|
||||
"Share", // STR_SHARE
|
||||
"310 Failed", // STR_FAILED
|
||||
"310 Failed to create file on local", // STR_FAIL_CREATE_LOCAL_FILE_MSG
|
||||
"Install", // STR_INSTALL
|
||||
"Installing", // STR_INSTALLING
|
||||
"Success", // STR_INSTALL_SUCCESS
|
||||
"Failed", // STR_INSTALL_FAILED
|
||||
"Skipped", // STR_INSTALL_SKIPPED
|
||||
"Checking connection to remote HTTP Server", // STR_CHECK_HTTP_MSG
|
||||
"Failed connecting to HTTP Server", // STR_FAILED_HTTP_CHECK
|
||||
"Remote is not a HTTP Server", // STR_REMOTE_NOT_HTTP
|
||||
"Package not in the /data or /mnt/usbX folder", // STR_INSTALL_FROM_DATA_MSG
|
||||
"Package is already installed", // STR_ALREADY_INSTALLED_MSG
|
||||
"Install from URL", // STR_INSTALL_FROM_URL
|
||||
"Could not read package header info", // STR_CANNOT_READ_PKG_HDR_MSG
|
||||
"Favorite URLs", // STR_FAVORITE_URLS
|
||||
"Slot", // STR_SLOT
|
||||
"Edit", // STR_EDIT
|
||||
"One Time Url", // STR_ONETIME_URL
|
||||
"Not a valid Package", // STR_NOT_A_VALID_PACKAGE
|
||||
"Waiting for Package to finish installing", // STR_WAIT_FOR_INSTALL_MSG
|
||||
"Failed to install pkg file. Please delete the tmp pkg manually", // STR_FAIL_INSTALL_TMP_PKG_MSG
|
||||
"Failed to obtain google download URL", // STR_FAIL_TO_OBTAIN_GG_DL_MSG
|
||||
"Auto delete temporary downloaded pkg file after install", // STR_AUTO_DELETE_TMP_PKG
|
||||
"Protocol not supported", // STR_PROTOCOL_NOT_SUPPORTED
|
||||
"Could not resolve hostname", // STR_COULD_NOT_RESOLVE_HOST
|
||||
"Extract", // STR_EXTRACT
|
||||
"Extracting", // STR_EXTRACTING
|
||||
"Failed to extract", // STR_FAILED_TO_EXTRACT
|
||||
"Extract Location", // STR_EXTRACT_LOCATION
|
||||
"Compress", // STR_COMPRESS
|
||||
"Zip Filename", // STR_ZIP_FILE_PATH
|
||||
"Compressing", // STR_COMPRESSING
|
||||
"Error occured while creating zip", // STR_ERROR_CREATE_ZIP
|
||||
"Unsupported compressed file format", // STR_UNSUPPORTED_FILE_FORMAT
|
||||
"Cut", // STR_CUT
|
||||
"Copy", // STR_COPY
|
||||
"Paste", // STR_PASTE
|
||||
"Moving", // STR_MOVING
|
||||
"Copying", // STR_COPYING
|
||||
"Failed to move file", // STR_FAIL_MOVE_MSG
|
||||
"Failed to copy file", // STR_FAIL_COPY_MSG
|
||||
"Cannot move parent directory to sub subdirectory", // STR_CANT_MOVE_TO_SUBDIR_MSG
|
||||
"Cannot copy parent directory to sub subdirectory", // STR_CANT_COPY_TO_SUBDIR_MSG
|
||||
"Operation not supported", // STR_UNSUPPORTED_OPERATION_MSG
|
||||
"Http Port", // STR_HTTP_PORT
|
||||
"The content has already been installed. Do you want to continue installing", // STR_REINSTALL_CONFIRM_MSG
|
||||
"Remote package installation is not supported for protected servers.", // STR_REMOTE_NOT_SUPPORT_MSG
|
||||
"Remote HTTP Server not reachable.", // STR_CANNOT_CONNECT_REMOTE_MSG
|
||||
"Remote Package Install not possible. Would you like to download package and install?", // STR_DOWNLOAD_INSTALL_MSG
|
||||
"Checking remote server for Remote Package Install.", // STR_CHECKING_REMOTE_SERVER_MSG
|
||||
"RPI", // STR_ENABLE_RPI
|
||||
"This option enables Remote Package Installation. "
|
||||
"This requires a HTTP Server setup on the same host sharing the same folder with anonymous access.", // STR_ENABLE_RPI_FTP_SMB_MSG
|
||||
"This option enables Remote Package Installation. "
|
||||
"This requires the Server with anonymous access that does not need username/password.", // STR_ENABLE_RPI_WEBDAV_MSG
|
||||
"Connection Settings", // STR_CONNECTION_SETTINGS
|
||||
"Site", // STR_SITE
|
||||
"Local", // STR_LOCAL
|
||||
"Remote", // STR_REMOTE
|
||||
"Messages", // STR_MESSAGES
|
||||
"Update Software", // STR_UPDATE_SOFTWARE
|
||||
"Connect", // STR_CONNECT
|
||||
"Disconnect", // STR_DISCONNECT
|
||||
"Search", // STR_SEARCH
|
||||
"Refresh", // STR_REFRESH
|
||||
"Server", // STR_SERVER
|
||||
"Username", // STR_USERNAME
|
||||
"Password", // STR_PASSWORD
|
||||
"Port", // STR_PORT
|
||||
"Pasv", // STR_PASV
|
||||
"Directory", // STR_DIRECTORY
|
||||
"Filter", // STR_FILTER
|
||||
"Yes", // STR_YES
|
||||
"No", // STR_NO
|
||||
"Cancel", // STR_CANCEL
|
||||
"Continue", // STR_CONTINUE
|
||||
"Close", // STR_CLOSE
|
||||
"Folder", // STR_FOLDER
|
||||
"File", // STR_FILE
|
||||
"Type", // STR_TYPE
|
||||
"Name", // STR_NAME
|
||||
"Size", // STR_SIZE
|
||||
"Date", // STR_DATE
|
||||
"New Folder", // STR_NEW_FOLDER
|
||||
"Rename", // STR_RENAME
|
||||
"Delete", // STR_DELETE
|
||||
"Upload", // STR_UPLOAD
|
||||
"Download", // STR_DOWNLOAD
|
||||
"Select All", // STR_SELECT_ALL
|
||||
"Clear All", // STR_CLEAR_ALL
|
||||
"Uploading", // STR_UPLOADING
|
||||
"Downloading", // STR_DOWNLOADING
|
||||
"Overwrite", // STR_OVERWRITE
|
||||
"Don't Overwrite", // STR_DONT_OVERWRITE
|
||||
"Ask for Confirmation", // STR_ASK_FOR_CONFIRM
|
||||
"Don't Ask for Confirmation", // STR_DONT_ASK_CONFIRM
|
||||
"Always use this option and don't ask again", // STR_ALLWAYS_USE_OPTION
|
||||
"Actions", // STR_ACTIONS
|
||||
"Confirm", // STR_CONFIRM
|
||||
"Overwrite Options", // STR_OVERWRITE_OPTIONS
|
||||
"Properties", // STR_PROPERTIES
|
||||
"Progress", // STR_PROGRESS
|
||||
"Updates", // STR_UPDATES
|
||||
"Are you sure you want to delete this file(s)/folder(s)?", // STR_DEL_CONFIRM_MSG
|
||||
"Canceling. Waiting for last action to complete", // STR_CANCEL_ACTION_MSG
|
||||
"Failed to upload file", // STR_FAIL_UPLOAD_MSG
|
||||
"Failed to download file", // STR_FAIL_DOWNLOAD_MSG
|
||||
"Failed to read contents of directory or folder does not exist.", // STR_FAIL_READ_LOCAL_DIR_MSG
|
||||
"426 Connection closed.", // STR_CONNECTION_CLOSE_ERR_MSG
|
||||
"426 Remote Server has terminated the connection.", // STR_REMOTE_TERM_CONN_MSG
|
||||
"300 Failed Login. Please check your username or password.", // STR_FAIL_LOGIN_MSG
|
||||
"426 Failed. Connection timeout.", // STR_FAIL_TIMEOUT_MSG
|
||||
"Failed to delete directory", // STR_FAIL_DEL_DIR_MSG
|
||||
"Deleting", // STR_DELETING
|
||||
"Failed to delete file", // STR_FAIL_DEL_FILE_MSG
|
||||
"Deleted", // STR_DELETED
|
||||
"Link", // STR_LINK
|
||||
"Share", // STR_SHARE
|
||||
"310 Failed", // STR_FAILED
|
||||
"310 Failed to create file on local", // STR_FAIL_CREATE_LOCAL_FILE_MSG
|
||||
"Install", // STR_INSTALL
|
||||
"Installing", // STR_INSTALLING
|
||||
"Success", // STR_INSTALL_SUCCESS
|
||||
"Failed", // STR_INSTALL_FAILED
|
||||
"Skipped", // STR_INSTALL_SKIPPED
|
||||
"Checking connection to remote HTTP Server", // STR_CHECK_HTTP_MSG
|
||||
"Failed connecting to HTTP Server", // STR_FAILED_HTTP_CHECK
|
||||
"Remote is not a HTTP Server", // STR_REMOTE_NOT_HTTP
|
||||
"Package not in the /data or /mnt/usbX folder", // STR_INSTALL_FROM_DATA_MSG
|
||||
"Package is already installed", // STR_ALREADY_INSTALLED_MSG
|
||||
"Install from URL", // STR_INSTALL_FROM_URL
|
||||
"Could not read package header info", // STR_CANNOT_READ_PKG_HDR_MSG
|
||||
"Favorite URLs", // STR_FAVORITE_URLS
|
||||
"Slot", // STR_SLOT
|
||||
"Edit", // STR_EDIT
|
||||
"One Time Url", // STR_ONETIME_URL
|
||||
"Not a valid Package", // STR_NOT_A_VALID_PACKAGE
|
||||
"Waiting for Package to finish installing", // STR_WAIT_FOR_INSTALL_MSG
|
||||
"Failed to install pkg file. Please delete the tmp pkg manually", // STR_FAIL_INSTALL_TMP_PKG_MSG
|
||||
"Failed to obtain google download URL", // STR_FAIL_TO_OBTAIN_GG_DL_MSG
|
||||
"Auto delete temporary downloaded pkg file after install", // STR_AUTO_DELETE_TMP_PKG
|
||||
"Protocol not supported", // STR_PROTOCOL_NOT_SUPPORTED
|
||||
"Could not resolve hostname", // STR_COULD_NOT_RESOLVE_HOST
|
||||
"Extract", // STR_EXTRACT
|
||||
"Extracting", // STR_EXTRACTING
|
||||
"Failed to extract", // STR_FAILED_TO_EXTRACT
|
||||
"Extract Location", // STR_EXTRACT_LOCATION
|
||||
"Compress", // STR_COMPRESS
|
||||
"Zip Filename", // STR_ZIP_FILE_PATH
|
||||
"Compressing", // STR_COMPRESSING
|
||||
"Error occured while creating zip", // STR_ERROR_CREATE_ZIP
|
||||
"Unsupported compressed file format", // STR_UNSUPPORTED_FILE_FORMAT
|
||||
"Cut", // STR_CUT
|
||||
"Copy", // STR_COPY
|
||||
"Paste", // STR_PASTE
|
||||
"Moving", // STR_MOVING
|
||||
"Copying", // STR_COPYING
|
||||
"Failed to move file", // STR_FAIL_MOVE_MSG
|
||||
"Failed to copy file", // STR_FAIL_COPY_MSG
|
||||
"Cannot move parent directory to sub subdirectory", // STR_CANT_MOVE_TO_SUBDIR_MSG
|
||||
"Cannot copy parent directory to sub subdirectory", // STR_CANT_COPY_TO_SUBDIR_MSG
|
||||
"Operation not supported", // STR_UNSUPPORTED_OPERATION_MSG
|
||||
"Http Port", // STR_HTTP_PORT
|
||||
"The content has already been installed. Do you want to continue installing", // STR_REINSTALL_CONFIRM_MSG
|
||||
"Remote package installation is not supported for protected servers.", // STR_REMOTE_NOT_SUPPORT_MSG
|
||||
"Remote HTTP Server not reachable.", // STR_CANNOT_CONNECT_REMOTE_MSG
|
||||
"Remote Package Install not possible. Would you like to download package and install?", // STR_DOWNLOAD_INSTALL_MSG
|
||||
"Checking remote server for Remote Package Install.", // STR_CHECKING_REMOTE_SERVER_MSG
|
||||
"RPI", // STR_ENABLE_RPI
|
||||
"This option enables Remote Package Installation.", // STR_ENABLE_RPI_FTP_SMB_MSG
|
||||
"This option enables Remote Package Installation.", // STR_ENABLE_RPI_WEBDAV_MSG
|
||||
"Files", // STR_FILES
|
||||
"Editor", // STR_EDITOR
|
||||
"Save", // STR_SAVE
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
#include <string>
|
||||
#include <json-c/json.h>
|
||||
#include <range_parser/range_parser.hpp>
|
||||
#include "http/httplib.h"
|
||||
#include "server/http_server.h"
|
||||
#include "clients/gdrive.h"
|
||||
#include "clients/sftpclient.h"
|
||||
#include "clients/smbclient.h"
|
||||
#include "clients/ftpclient.h"
|
||||
#include "clients/nfsclient.h"
|
||||
#include "config.h"
|
||||
#include "fs.h"
|
||||
#include "windows.h"
|
||||
@@ -19,6 +24,7 @@
|
||||
#define SUCCESS_MSG_LEN 48
|
||||
|
||||
using namespace httplib;
|
||||
|
||||
Server *svr;
|
||||
int http_server_port = 8080;
|
||||
char compressed_file_path[1024];
|
||||
@@ -382,7 +388,15 @@ namespace HttpServer
|
||||
{
|
||||
const char *src = json_object_get_string(json_object_array_get_idx(items, 0));
|
||||
std::string dest = std::string(newPath) + "/" + singleFilename;
|
||||
if (dest.compare(src) != 0 && !FS::Copy(src, dest))
|
||||
|
||||
std::string temp = std::string(src);
|
||||
size_t slash_pos = temp.find_last_of("/");
|
||||
DirEntry entry;
|
||||
sprintf(entry.name, "%s", temp.substr(slash_pos+1).c_str());
|
||||
sprintf(entry.path, "%s", src);
|
||||
entry.isDir = FS::IsFolder(src);
|
||||
if (entry.isDir)
|
||||
if (dest.compare(src) != 0 && !CopyOrMove(entry, dest.c_str(), true))
|
||||
{
|
||||
failed_items += src;
|
||||
}
|
||||
@@ -699,6 +713,7 @@ namespace HttpServer
|
||||
size_t chunk_size = 0;
|
||||
size_t chunk_number = -1;
|
||||
size_t total_size = 0;
|
||||
size_t currentChunkSize = 0;
|
||||
FILE *out = nullptr;
|
||||
std::string new_file;
|
||||
content_reader(
|
||||
@@ -742,6 +757,11 @@ namespace HttpServer
|
||||
std::stringstream ss(items.back().content);
|
||||
ss >> total_size;
|
||||
}
|
||||
else if (items.back().name == "_currentChunkSize")
|
||||
{
|
||||
std::stringstream ss(items.back().content);
|
||||
ss >> currentChunkSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (out != nullptr)
|
||||
@@ -900,6 +920,110 @@ namespace HttpServer
|
||||
res.set_content(str.c_str(), "text/plain");
|
||||
});
|
||||
|
||||
svr->Get("/rmt_inst/(.*)", [&](const Request & req, Response & res)
|
||||
{
|
||||
RemoteClient *tmp_client;
|
||||
auto path = std::string("/") + std::string(req.matches[1]);
|
||||
|
||||
if (remote_settings->type == CLIENT_TYPE_SFTP)
|
||||
{
|
||||
tmp_client = new SFTPClient();
|
||||
tmp_client->Connect(remote_settings->server, remote_settings->username, remote_settings->password);
|
||||
}
|
||||
else if (remote_settings->type == CLIENT_TYPE_SMB)
|
||||
{
|
||||
tmp_client = new SmbClient();
|
||||
tmp_client->Connect(remote_settings->server, remote_settings->username, remote_settings->password);
|
||||
}
|
||||
else if (remote_settings->type == CLIENT_TYPE_FTP)
|
||||
{
|
||||
tmp_client = new FtpClient();
|
||||
tmp_client->Connect(remote_settings->server, remote_settings->username, remote_settings->password);
|
||||
}
|
||||
else if (remote_settings->type == CLIENT_TYPE_NFS)
|
||||
{
|
||||
tmp_client = new NfsClient();
|
||||
tmp_client->Connect(remote_settings->server, remote_settings->username, remote_settings->password);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_client = remoteclient;
|
||||
}
|
||||
|
||||
if (tmp_client == nullptr || !tmp_client->IsConnected())
|
||||
{
|
||||
res.status = 404;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (req.method == "HEAD")
|
||||
{
|
||||
int64_t file_size;
|
||||
int ret;
|
||||
ret = tmp_client->Size(path, &file_size);
|
||||
if (!ret)
|
||||
{
|
||||
res.status = 500;
|
||||
return;
|
||||
}
|
||||
|
||||
res.status = 204;
|
||||
res.set_header("Content-Length", std::to_string(file_size));
|
||||
res.set_header("Accept-Ranges", "bytes");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.ranges.empty())
|
||||
{
|
||||
res.status = 200;
|
||||
res.set_content_provider(
|
||||
(1024*128), "application/octet-stream",
|
||||
[tmp_client, path](size_t offset, size_t length, DataSink &sink) {
|
||||
int ret = tmp_client->GetRange(path, sink, length, offset);
|
||||
return (ret == 1);
|
||||
},
|
||||
[tmp_client, path](bool success) {
|
||||
if (tmp_client != nullptr && (tmp_client->clientType() == CLIENT_TYPE_SFTP
|
||||
|| tmp_client->clientType() == CLIENT_TYPE_SMB
|
||||
|| tmp_client->clientType() == CLIENT_TYPE_FTP
|
||||
|| tmp_client->clientType() == CLIENT_TYPE_NFS))
|
||||
{
|
||||
tmp_client->Quit();
|
||||
delete tmp_client;
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status = 206;
|
||||
size_t range_len = (req.ranges[0].second - req.ranges[0].first) + 1;
|
||||
if (req.ranges[0].second >= 18000000000000000000ul)
|
||||
{
|
||||
range_len = 65536ul - req.ranges[0].first;
|
||||
res.set_header("Content-Length", std::to_string(range_len));
|
||||
res.set_header("Content-Range", std::string("bytes ") + std::to_string(req.ranges[0].first)+"-65535/"+std::to_string(range_len));
|
||||
}
|
||||
std::pair<ssize_t, ssize_t> range = req.ranges[0];
|
||||
res.set_content_provider(
|
||||
range_len, "application/octet-stream",
|
||||
[tmp_client, path, range, range_len](size_t offset, size_t length, DataSink &sink) {
|
||||
int ret = tmp_client->GetRange(path, sink, range_len, range.first);
|
||||
return (ret == 1);
|
||||
},
|
||||
[tmp_client, path, range, range_len](bool success) {
|
||||
if (tmp_client != nullptr && (tmp_client->clientType() == CLIENT_TYPE_SFTP
|
||||
|| tmp_client->clientType() == CLIENT_TYPE_SMB
|
||||
|| tmp_client->clientType() == CLIENT_TYPE_FTP
|
||||
|| tmp_client->clientType() == CLIENT_TYPE_NFS))
|
||||
{
|
||||
tmp_client->Quit();
|
||||
delete tmp_client;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
svr->Get("/stop", [&](const Request & /*req*/, Response & /*res*/)
|
||||
{
|
||||
svr->stop();
|
||||
|
||||
@@ -23,9 +23,12 @@
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include "http/httplib.h"
|
||||
|
||||
#include "callback.hpp"
|
||||
|
||||
using namespace httplib;
|
||||
|
||||
namespace Web
|
||||
{
|
||||
namespace Callback
|
||||
@@ -104,6 +107,14 @@ namespace Web
|
||||
out_stream->write(ptr, write_bytes);
|
||||
return write_bytes;
|
||||
}
|
||||
|
||||
size_t stream2sink(char* ptr, size_t item_size, size_t item_count, void* sink)
|
||||
{
|
||||
auto ostream = reinterpret_cast<DataSink*>(sink);
|
||||
size_t write_bytes = item_size * item_count;
|
||||
ostream->write(ptr, write_bytes);
|
||||
return write_bytes;
|
||||
}
|
||||
} // namespace Append
|
||||
} // namespace Callback
|
||||
} // namespace Web
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace Web
|
||||
{
|
||||
size_t stream(char* data, size_t size, size_t count, void* stream);
|
||||
size_t buffer(char* data, size_t size, size_t count, void* buffer);
|
||||
size_t stream2sink(char* ptr, size_t item_size, size_t item_count, void* sink);
|
||||
}
|
||||
}
|
||||
} // namespace Web
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "web/request.hpp"
|
||||
#include "web/urn.hpp"
|
||||
#include "util.h"
|
||||
#include "http/httplib.h"
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
|
||||
@@ -234,6 +235,57 @@ bool
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Client::sync_download_range_to(
|
||||
const std::string &remote_file,
|
||||
DataSink &sink,
|
||||
uint64_t range_from,
|
||||
uint64_t range_to,
|
||||
callback_t callback,
|
||||
progress_data_t progress_data,
|
||||
progress_t progress)
|
||||
{
|
||||
bool is_existed = this->check(remote_file);
|
||||
if (!is_existed)
|
||||
return false;
|
||||
|
||||
auto root_urn = Path(this->webdav_root, true);
|
||||
auto file_urn = root_urn + remote_file;
|
||||
|
||||
Request request(this->options());
|
||||
|
||||
auto url = this->webdav_hostname + file_urn.quote(request.handle);
|
||||
struct curl_slist *list = NULL;
|
||||
char range_header[64];
|
||||
sprintf(range_header, "Range: bytes=%lu-%lu", range_from, range_to);
|
||||
list = curl_slist_append(list, range_header);
|
||||
request.set(CURLOPT_CUSTOMREQUEST, "GET");
|
||||
request.set(CURLOPT_URL, url.c_str());
|
||||
request.set(CURLOPT_HEADER, 0L);
|
||||
request.set(CURLOPT_HTTPHEADER, list);
|
||||
request.set(CURLOPT_WRITEDATA, reinterpret_cast<void*>(&sink));
|
||||
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Append::stream2sink));
|
||||
#ifdef WDC_VERBOSE
|
||||
request.set(CURLOPT_VERBOSE, 1);
|
||||
#endif
|
||||
if (progress != nullptr)
|
||||
{
|
||||
request.set(CURLOPT_XFERINFODATA, progress_data);
|
||||
request.set(CURLOPT_XFERINFOFUNCTION, progress);
|
||||
request.set(CURLOPT_NOPROGRESS, 0L);
|
||||
}
|
||||
|
||||
bool is_performed = request.perform();
|
||||
this->http_code = request.status_code();
|
||||
this->result = request.result();
|
||||
if (callback != nullptr)
|
||||
callback(is_performed);
|
||||
if (!is_performed)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Client::sync_download_to(
|
||||
const std::string &remote_file,
|
||||
@@ -777,6 +829,18 @@ bool
|
||||
return this->sync_download_range_to(remote_file, buffer_ptr, buffer_size, range_from, range_to, nullptr, progress_data, std::move(progress));
|
||||
}
|
||||
|
||||
bool
|
||||
Client::download_range_to(
|
||||
const std::string &remote_file,
|
||||
DataSink &sink,
|
||||
uint64_t range_from,
|
||||
uint64_t range_to,
|
||||
progress_data_t progress_data,
|
||||
progress_t progress)
|
||||
{
|
||||
return this->sync_download_range_to(remote_file, sink, range_from, range_to, nullptr, progress_data, std::move(progress));
|
||||
}
|
||||
|
||||
bool
|
||||
Client::download_to(
|
||||
const std::string &remote_file,
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <curl/curl.h>
|
||||
#include "http/httplib.h"
|
||||
|
||||
using namespace httplib;
|
||||
|
||||
namespace WebDAV
|
||||
{
|
||||
@@ -208,6 +211,24 @@ namespace WebDAV
|
||||
progress_t progress = nullptr
|
||||
) -> bool;
|
||||
|
||||
///
|
||||
/// Download a remote file to a buffer for specified range
|
||||
/// \param[in] remote_file
|
||||
/// \param[out] sink,
|
||||
/// \param[in] range_from,
|
||||
/// \param[in] range_to
|
||||
/// \param[in] progress
|
||||
/// \snippet client/download.cpp download_to_buffer
|
||||
///
|
||||
auto download_range_to(
|
||||
const std::string &remote_file,
|
||||
DataSink &sink,
|
||||
uint64_t range_from,
|
||||
uint64_t range_to,
|
||||
progress_data_t progress_data = nullptr,
|
||||
progress_t progress = nullptr
|
||||
) -> bool;
|
||||
|
||||
///
|
||||
/// Download a remote file to a stream
|
||||
/// \param[in] remote_file
|
||||
@@ -330,6 +351,16 @@ namespace WebDAV
|
||||
progress_t progress = nullptr
|
||||
) -> bool;
|
||||
|
||||
auto sync_download_range_to(
|
||||
const std::string &remote_file,
|
||||
DataSink &sink,
|
||||
uint64_t range_from,
|
||||
uint64_t range_to,
|
||||
callback_t callback,
|
||||
progress_data_t progress_data,
|
||||
progress_t progress
|
||||
) -> bool;
|
||||
|
||||
bool sync_download_to(
|
||||
const std::string& remote_file,
|
||||
std::ostream& stream,
|
||||
|
||||
+28
-56
@@ -39,7 +39,6 @@ static char *ime_single_field;
|
||||
static int ime_field_size;
|
||||
|
||||
static char txt_http_server_port[6];
|
||||
static char txt_http_port[6];
|
||||
|
||||
bool handle_updates = false;
|
||||
int64_t bytes_transfered;
|
||||
@@ -118,7 +117,6 @@ namespace Windows
|
||||
sprintf(status_message, "");
|
||||
sprintf(local_filter, "");
|
||||
sprintf(remote_filter, "");
|
||||
sprintf(txt_http_port, "%d", remote_settings->http_port);
|
||||
sprintf(txt_http_server_port, "%d", http_server_port);
|
||||
dont_prompt_overwrite = false;
|
||||
confirm_transfer_state = -1;
|
||||
@@ -320,7 +318,6 @@ namespace Windows
|
||||
sprintf(display_site, "%s", site_id);
|
||||
remote_settings = &site_settings[sites[n]];
|
||||
sprintf(remote_directory, "%s", remote_settings->default_directory);
|
||||
sprintf(txt_http_port, "%d", remote_settings->http_port);
|
||||
}
|
||||
|
||||
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
|
||||
@@ -402,66 +399,42 @@ namespace Windows
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
if (remote_settings->type != CLIENT_TYPE_GOOGLE)
|
||||
if (remote_settings->type != CLIENT_TYPE_NFS && remote_settings->type != CLIENT_TYPE_GOOGLE)
|
||||
{
|
||||
if (remote_settings->type != CLIENT_TYPE_NFS)
|
||||
{
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_PASSWORD]);
|
||||
ImGui::SameLine();
|
||||
|
||||
sprintf(id, "%s##password", hidden_password.c_str());
|
||||
pos = ImGui::GetCursorPos();
|
||||
if (ImGui::Button(id, ImVec2(100, 0)))
|
||||
{
|
||||
ime_single_field = remote_settings->password;
|
||||
ResetImeCallbacks();
|
||||
ime_field_size = 127;
|
||||
ime_callback = SingleValueImeCallback;
|
||||
Dialog::initImeDialog(lang_strings[STR_PASSWORD], remote_settings->password, 127, ORBIS_TYPE_BASIC_LATIN, pos.x, pos.y);
|
||||
gui_mode = GUI_MODE_IME;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_ENABLE_RPI]);
|
||||
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_PASSWORD]);
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Checkbox("###enable_rpi", &remote_settings->enable_rpi))
|
||||
sprintf(id, "%s##password", hidden_password.c_str());
|
||||
pos = ImGui::GetCursorPos();
|
||||
if (ImGui::Button(id, ImVec2(100, 0)))
|
||||
{
|
||||
CONFIG::SaveConfig();
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(450, 135));
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 440);
|
||||
ImGui::Text("%s", (remote_settings->type == CLIENT_TYPE_SMB || remote_settings->type == CLIENT_TYPE_FTP) ? lang_strings[STR_ENABLE_RPI_FTP_SMB_MSG] : lang_strings[STR_ENABLE_RPI_WEBDAV_MSG]);
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
ime_single_field = remote_settings->password;
|
||||
ResetImeCallbacks();
|
||||
ime_field_size = 127;
|
||||
ime_callback = SingleValueImeCallback;
|
||||
Dialog::initImeDialog(lang_strings[STR_PASSWORD], remote_settings->password, 127, ORBIS_TYPE_BASIC_LATIN, pos.x, pos.y);
|
||||
gui_mode = GUI_MODE_IME;
|
||||
}
|
||||
}
|
||||
|
||||
if ((remote_settings->type == CLIENT_TYPE_NFS || remote_settings->type == CLIENT_TYPE_SMB || remote_settings->type == CLIENT_TYPE_FTP) && remote_settings->enable_rpi)
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_HTTP_PORT]);
|
||||
ImGui::SameLine();
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_ENABLE_RPI]);
|
||||
ImGui::SameLine();
|
||||
|
||||
sprintf(id, "%s##http_port", txt_http_port);
|
||||
pos = ImGui::GetCursorPos();
|
||||
if (ImGui::Button(id, ImVec2(65, 0)))
|
||||
{
|
||||
ime_single_field = txt_http_port;
|
||||
ResetImeCallbacks();
|
||||
ime_field_size = 24;
|
||||
ime_callback = SingleValueImeCallback;
|
||||
ime_after_update = AfterHttpPortChangeCallback;
|
||||
Dialog::initImeDialog(lang_strings[STR_PASSWORD], txt_http_port, 24, ORBIS_TYPE_NUMBER, pos.x, pos.y);
|
||||
gui_mode = GUI_MODE_IME;
|
||||
}
|
||||
}
|
||||
if (ImGui::Checkbox("###enable_rpi", &remote_settings->enable_rpi))
|
||||
{
|
||||
CONFIG::SaveConfig();
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(450, 70));
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 440);
|
||||
ImGui::Text("%s", lang_strings[STR_ENABLE_RPI_FTP_SMB_MSG]);
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
@@ -2399,7 +2372,6 @@ namespace Windows
|
||||
{
|
||||
if (ime_result == IME_DIALOG_RESULT_FINISHED)
|
||||
{
|
||||
remote_settings->http_port = atoi(txt_http_port);
|
||||
http_server_port = atoi(txt_http_server_port);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user