Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ed3e2c049b | |||
| 5d5f22e61b | |||
| dbf51d7a7c | |||
| 880ac0042f | |||
| 21204b2b55 | |||
| 10f3cafa1c |
+3
-1
@@ -35,6 +35,7 @@ add_executable(ezremote_client
|
||||
source/clients/iis.cpp
|
||||
source/clients/nginx.cpp
|
||||
source/clients/npxserve.cpp
|
||||
source/clients/nfsclient.cpp
|
||||
source/clients/smbclient.cpp
|
||||
source/clients/webdavclient.cpp
|
||||
source/clients/sftpclient.cpp
|
||||
@@ -60,7 +61,7 @@ add_executable(ezremote_client
|
||||
|
||||
add_self(ezremote_client)
|
||||
|
||||
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.06" 32 0)
|
||||
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.07" 32 0)
|
||||
|
||||
target_link_libraries(ezremote_client
|
||||
c
|
||||
@@ -79,6 +80,7 @@ target_link_libraries(ezremote_client
|
||||
curl
|
||||
lexbor
|
||||
smb2
|
||||
nfs
|
||||
minizip
|
||||
un7zip
|
||||
unrar
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# ezRemote Client
|
||||
|
||||
ezRemote Client is an application that allows you to connect the PS4 to remote FTP/SFTP, SMB, WebDAV, HTTP servers and Google Drive to transfer files. The interface is inspired by Filezilla client which provides a commander like GUI.
|
||||
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.
|
||||

|
||||
## Usage
|
||||
To distinguish between FTP, SMB, WebDAV or HTTP, the URL must be prefix with **ftp://**, **sftp://**, **smb://**, **webdav://**, **webdavs://**, **http://** and **https://**
|
||||
To distinguish between FTP, SMB, NFS, WebDAV or HTTP, the URL must be prefix with **ftp://**, **sftp://**, **smb://**, **nfs://**, **webdav://**, **webdavs://**, **http://** and **https://**
|
||||
|
||||
- The url format for FTP is
|
||||
```
|
||||
@@ -28,6 +28,29 @@ To distinguish between FTP, SMB, WebDAV or HTTP, the URL must be prefix with **f
|
||||
- sharename is required
|
||||
```
|
||||
|
||||
- The url format for NFS is
|
||||
```
|
||||
nfs://hostname[:port]/export_path[?arg=val[&arg=val]*]
|
||||
|
||||
- hostname can be the textual hostname or an IP address. hostname is required
|
||||
- port is optional and defaults to 2049 if not provided
|
||||
- export_path is required
|
||||
|
||||
Special characters in 'path' are escaped using %-hex-hex syntax.
|
||||
|
||||
For example '?' must be escaped if it occurs in a path as '?' is also used to
|
||||
separate the path from the optional list of url arguments.
|
||||
|
||||
Example:
|
||||
nfs://192.168.0.1/my?path?uid=1000&gid=1000
|
||||
must be escaped as
|
||||
nfs://192.168.0.1/my%3Fpath?uid=1000&gid=1000
|
||||
|
||||
Arguments supported are :
|
||||
uid=<int> : UID value to use when talking to the server. Defaults to 65534 if not specified.
|
||||
gid=<int> : GID value to use when talking to the server. Defaults to 65534 if not specified.
|
||||
```
|
||||
|
||||
- The url format for WebDAV is
|
||||
```
|
||||
webdav://hostname[:port]/[url_path]
|
||||
@@ -61,7 +84,7 @@ Tested with following WebDAV server:
|
||||
Remote Package Installation only works if the WebDAV server allow anonymous access. It's a limitation of the PS4 Installer not able to access protected links. As suggested, use the [Dufs](https://github.com/sigoden/dufs) app for WebDAV.
|
||||
|
||||
## Features ##
|
||||
- Transfer files back and forth between PS4 and FTP/SMB/WebDAV server
|
||||
- Transfer files back and forth between PS4 and FTP/SMB/NFS/WebDAV server
|
||||
- Support for connecting to Http Servers like (Apache/Nginx,Microsoft IIS, Serve) with html directory listings to download or install pkg.
|
||||
- Install Remote Packages from connected WebDAV server
|
||||
- Ability to connect to your "Google Drive" to transfer files back and fort. Can also install packages from it. The app will download the file to the PS4's harddrive and then install it. You need to keep the app opened. Here is a link to the wiki for what you need to do to make it work. Also able to access files that are shared to you. As of v1.06, Google Shared Drives from Google workspace is supported.
|
||||
@@ -177,6 +200,8 @@ Build and install lexbor - https://github.com/lexbor/lexbor.git
|
||||
|
||||
Build and install libssh2 - https://www.libssh2.org/
|
||||
|
||||
Build and install libnfs - https://github.com/cy33hc/libnfs/tree/ps4
|
||||
|
||||
Build libjbc - https://github.com/cy33hc/ps4-libjbc/blob/master/README_PS4.md
|
||||
|
||||
Build libunrar - https://github.com/cy33hc/libunrar-ps3
|
||||
|
||||
@@ -143,3 +143,5 @@ STR_SET_DEFAULT_DIRECTORY=Set Default Folder
|
||||
STR_SET_DEFAULT_DIRECTORY_MSG=has being set as default direcotry
|
||||
STR_VIEW_IMAGE=View Image
|
||||
STR_VIEW_PKG_INFO=Package Information
|
||||
STR_NFS_EXP_PATH_MISSING_MSG=NFS export path missing in URL
|
||||
STR_FAIL_INIT_NFS_CONTEXT=Failed to init NFS context
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "clients/apache.h"
|
||||
#include "clients/nginx.h"
|
||||
#include "clients/npxserve.h"
|
||||
#include "clients/nfsclient.h"
|
||||
#include "clients/iis.h"
|
||||
#include "clients/sftpclient.h"
|
||||
#include "common.h"
|
||||
@@ -1146,6 +1147,10 @@ namespace Actions
|
||||
{
|
||||
remoteclient = new SFTPClient();
|
||||
}
|
||||
else if (strncmp(remote_settings->server, "nfs://", 6) == 0)
|
||||
{
|
||||
remoteclient = new NfsClient();
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(status_message, "%s", lang_strings[STR_PROTOCOL_NOT_SUPPORTED]);
|
||||
|
||||
@@ -0,0 +1,519 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
#include <orbis/Net.h>
|
||||
#include "fs.h"
|
||||
#include "lang.h"
|
||||
#include "clients/nfsclient.h"
|
||||
#include "windows.h"
|
||||
#include "util.h"
|
||||
#include "system.h"
|
||||
|
||||
#define BUF_SIZE 64*1024
|
||||
|
||||
NfsClient::NfsClient()
|
||||
{
|
||||
}
|
||||
|
||||
NfsClient::~NfsClient()
|
||||
{
|
||||
}
|
||||
|
||||
int NfsClient::Connect(const std::string &url, const std::string &user, const std::string &pass)
|
||||
{
|
||||
nfs = nfs_init_context();
|
||||
if (nfs == nullptr)
|
||||
{
|
||||
sprintf(response, "%s", lang_strings[STR_FAIL_INIT_NFS_CONTEXT]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nfs_url *nfsurl = nfs_parse_url_full(nfs, url.c_str());
|
||||
if (nfsurl == nullptr) {
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
nfs_destroy_context(nfs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string export_path = std::string(nfsurl->path) + nfsurl->file;
|
||||
int ret = nfs_mount(nfs, nfsurl->server, export_path.c_str());
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
nfs_destroy_url(nfsurl);
|
||||
nfs_destroy_context(nfs);
|
||||
nfs = nullptr;
|
||||
return 0;
|
||||
}
|
||||
nfs_destroy_url(nfsurl);
|
||||
|
||||
connected = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* LastResponse - return a pointer to the last response received
|
||||
*/
|
||||
const char *NfsClient::LastResponse()
|
||||
{
|
||||
return (const char *)response;
|
||||
}
|
||||
|
||||
/*
|
||||
* IsConnected - return true if connected to remote
|
||||
*/
|
||||
bool NfsClient::IsConnected()
|
||||
{
|
||||
return connected;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ping - return true if connected to remote
|
||||
*/
|
||||
bool NfsClient::Ping()
|
||||
{
|
||||
return connected;
|
||||
}
|
||||
|
||||
/*
|
||||
* Quit - disconnect from remote
|
||||
*
|
||||
* return 1 if successful, 0 otherwise
|
||||
*/
|
||||
int NfsClient::Quit()
|
||||
{
|
||||
if (nfs != nullptr)
|
||||
{
|
||||
nfs_umount(nfs);
|
||||
nfs_destroy_context(nfs);
|
||||
nfs = nullptr;
|
||||
}
|
||||
connected = false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mkdir - create a directory at server
|
||||
*
|
||||
* return 1 if successful, 0 otherwise
|
||||
*/
|
||||
int NfsClient::Mkdir(const std::string &ppath)
|
||||
{
|
||||
int ret = nfs_mkdir(nfs, ppath.c_str());
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rmdir - remove directory and all files under directory at remote
|
||||
*
|
||||
* return 1 if successful, 0 otherwise
|
||||
*/
|
||||
int NfsClient::_Rmdir(const std::string &ppath)
|
||||
{
|
||||
int ret = nfs_rmdir(nfs, ppath.c_str());
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rmdir - remove directory and all files under directory at remote
|
||||
*
|
||||
* return 1 if successful, 0 otherwise
|
||||
*/
|
||||
int NfsClient::Rmdir(const std::string &path, bool recursive)
|
||||
{
|
||||
if (stop_activity)
|
||||
return 1;
|
||||
|
||||
std::vector<DirEntry> list = ListDir(path);
|
||||
int ret;
|
||||
for (int i = 0; i < list.size(); i++)
|
||||
{
|
||||
if (stop_activity)
|
||||
return 1;
|
||||
|
||||
if (list[i].isDir && recursive)
|
||||
{
|
||||
if (strcmp(list[i].name, "..") == 0)
|
||||
continue;
|
||||
ret = Rmdir(list[i].path, recursive);
|
||||
if (ret == 0)
|
||||
{
|
||||
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_DIR_MSG], list[i].path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(activity_message, "%s %s\n", lang_strings[STR_DELETING], list[i].path);
|
||||
ret = Delete(list[i].path);
|
||||
if (ret == 0)
|
||||
{
|
||||
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_FILE_MSG], list[i].path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = _Rmdir(path);
|
||||
if (ret == 0)
|
||||
{
|
||||
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_DIR_MSG], path.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get - issue a GET command and write received data to output
|
||||
*
|
||||
* return 1 if successful, 0 otherwise
|
||||
*/
|
||||
|
||||
int NfsClient::Get(const std::string &outputfile, const std::string &ppath, uint64_t offset)
|
||||
{
|
||||
if (!Size(ppath.c_str(), &bytes_to_download))
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nfsfh *nfsfh = nullptr;
|
||||
int ret = nfs_open(nfs, ppath.c_str(), 0400, &nfsfh);
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE* out = FS::Create(outputfile);
|
||||
if (out == NULL)
|
||||
{
|
||||
sprintf(response, "%s", lang_strings[STR_FAILED]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *buff = malloc(BUF_SIZE);
|
||||
int count = 0;
|
||||
bytes_transfered = 0;
|
||||
while ((count = nfs_read(nfs, nfsfh, BUF_SIZE, buff)) > 0)
|
||||
{
|
||||
if (count < 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
FS::Close(out);
|
||||
nfs_close(nfs, nfsfh);
|
||||
free((void*)buff);
|
||||
return 0;
|
||||
}
|
||||
FS::Write(out, buff, count);
|
||||
bytes_transfered += count;
|
||||
}
|
||||
FS::Close(out);
|
||||
nfs_close(nfs, nfsfh);
|
||||
free((void*)buff);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NfsClient::GetRange(const std::string &ppath, void *buffer, uint64_t size, uint64_t offset)
|
||||
{
|
||||
if (!FileExists(ppath))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nfsfh *nfsfh = nullptr;
|
||||
int ret = nfs_open(nfs, ppath.c_str(), 0400, &nfsfh);
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = nfs_lseek(nfs, nfsfh, offset, SEEK_SET, NULL);
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = nfs_read(nfs, nfsfh, size, buffer);
|
||||
nfs_close(nfs, nfsfh);
|
||||
if (count != size)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NfsClient::Copy(const std::string &ffrom, const std::string &tto)
|
||||
{
|
||||
sprintf(response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NfsClient::Move(const std::string &ffrom, const std::string &tto)
|
||||
{
|
||||
sprintf(response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NfsClient::FileExists(const std::string &ppath)
|
||||
{
|
||||
nfs_stat_64 st;
|
||||
int ret = nfs_stat64(nfs, ppath.c_str(), &st);
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put - issue a PUT command and send data from input
|
||||
*
|
||||
* return 1 if successful, 0 otherwise
|
||||
*/
|
||||
int NfsClient::Put(const std::string &inputfile, const std::string &ppath, uint64_t offset)
|
||||
{
|
||||
bytes_to_download = FS::GetSize(inputfile);
|
||||
if (bytes_to_download < 0)
|
||||
{
|
||||
sprintf(response, "%s", lang_strings[STR_FAILED]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE* in = FS::OpenRead(inputfile);
|
||||
if (in == NULL)
|
||||
{
|
||||
sprintf(response, "%s", lang_strings[STR_FAILED]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nfsfh *nfsfh = nullptr;
|
||||
int ret;
|
||||
if (!FileExists(ppath))
|
||||
ret = nfs_creat(nfs, ppath.c_str(), 0660, &nfsfh);
|
||||
else
|
||||
{
|
||||
ret = nfs_open(nfs, ppath.c_str(), 0660, &nfsfh);
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* buff = malloc(BUF_SIZE);
|
||||
uint64_t count = 0;
|
||||
bytes_transfered = 0;
|
||||
while ((count = FS::Read(in, buff, BUF_SIZE)) > 0)
|
||||
{
|
||||
if (count < 0)
|
||||
{
|
||||
sprintf(response, "%s", lang_strings[STR_FAILED]);
|
||||
FS::Close(in);
|
||||
nfs_close(nfs, nfsfh);
|
||||
free(buff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = nfs_write(nfs, nfsfh, count, buff);
|
||||
if (ret < 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
FS::Close(in);
|
||||
nfs_close(nfs, nfsfh);
|
||||
free(buff);
|
||||
return 0;
|
||||
}
|
||||
bytes_transfered += count;
|
||||
}
|
||||
FS::Close(in);
|
||||
nfs_close(nfs, nfsfh);
|
||||
free(buff);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NfsClient::Rename(const std::string &src, const std::string &dst)
|
||||
{
|
||||
int ret = nfs_rename(nfs, src.c_str(), dst.c_str());
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NfsClient::Delete(const std::string &ppath)
|
||||
{
|
||||
int ret = nfs_unlink(nfs, ppath.c_str());
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NfsClient::Size(const std::string &ppath, int64_t *size)
|
||||
{
|
||||
nfs_stat_64 st;
|
||||
int ret = nfs_stat64(nfs, ppath.c_str(), &st);
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return 0;
|
||||
}
|
||||
*size = st.nfs_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<DirEntry> NfsClient::ListDir(const std::string &path)
|
||||
{
|
||||
std::vector<DirEntry> out;
|
||||
DirEntry entry;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
out.push_back(entry);
|
||||
|
||||
struct nfsdir *nfsdir;
|
||||
struct nfsdirent *nfsdirent;
|
||||
|
||||
int ret = nfs_opendir(nfs, path.c_str(), &nfsdir);
|
||||
if (ret != 0) {
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return out;
|
||||
}
|
||||
|
||||
while ((nfsdirent = nfs_readdir(nfs, nfsdir)))
|
||||
{
|
||||
DirEntry entry;
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
|
||||
if (!show_hidden_files && nfsdirent->name[0] == '.')
|
||||
continue;
|
||||
|
||||
entry.selectable = true;
|
||||
snprintf(entry.directory, 511, "%s", path.c_str());
|
||||
snprintf(entry.name, 255, "%s", nfsdirent->name);
|
||||
if (path.length() > 0 && path[path.length() - 1] == '/')
|
||||
{
|
||||
sprintf(entry.path, "%s%s", path.c_str(), nfsdirent->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(entry.path, "%s/%s", path.c_str(), nfsdirent->name);
|
||||
}
|
||||
|
||||
entry.file_size = nfsdirent->size;
|
||||
struct tm tm = *localtime(&nfsdirent->mtime.tv_sec);
|
||||
OrbisDateTime gmt;
|
||||
OrbisDateTime lt;
|
||||
|
||||
gmt.day = tm.tm_mday;
|
||||
gmt.month = tm.tm_mon + 1;
|
||||
gmt.year = tm.tm_year + 1900;
|
||||
gmt.hour = tm.tm_hour;
|
||||
gmt.minute = tm.tm_min;
|
||||
gmt.second = tm.tm_sec;
|
||||
|
||||
convertUtcToLocalTime(&gmt, <);
|
||||
|
||||
entry.modified.day = lt.day;
|
||||
entry.modified.month = lt.month;
|
||||
entry.modified.year = lt.year;
|
||||
entry.modified.hours = lt.hour;
|
||||
entry.modified.minutes = lt.minute;
|
||||
entry.modified.seconds = lt.second;
|
||||
|
||||
switch (nfsdirent->mode & S_IFMT)
|
||||
{
|
||||
case S_IFLNK:
|
||||
entry.isLink = true;
|
||||
entry.file_size = 0;
|
||||
sprintf(entry.display_size, "%s", lang_strings[STR_LINK]);
|
||||
break;
|
||||
case S_IFREG:
|
||||
DirEntry::SetDisplaySize(&entry);
|
||||
break;
|
||||
case S_IFDIR:
|
||||
entry.isDir = true;
|
||||
entry.file_size = 0;
|
||||
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (strcmp(entry.name, "..") != 0 && strcmp(entry.name, ".") != 0)
|
||||
out.push_back(entry);
|
||||
|
||||
}
|
||||
nfs_closedir(nfs, nfsdir);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string NfsClient::GetPath(std::string ppath1, std::string ppath2)
|
||||
{
|
||||
std::string path1 = ppath1;
|
||||
std::string path2 = ppath2;
|
||||
path1 = Util::Trim(Util::Trim(path1, " "), "/");
|
||||
path2 = Util::Trim(Util::Trim(path2, " "), "/");
|
||||
path1 = "/" + path1 + "/" + path2;
|
||||
return path1;
|
||||
}
|
||||
|
||||
int NfsClient::Head(const std::string &ppath, void *buffer, uint64_t len)
|
||||
{
|
||||
if (!FileExists(ppath))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nfsfh *nfsfh = nullptr;
|
||||
int ret = nfs_open(nfs, ppath.c_str(), 0400, &nfsfh);
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf(response, "%s", nfs_get_error(nfs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = nfs_read(nfs, nfsfh, len, buffer);
|
||||
nfs_close(nfs, nfsfh);
|
||||
if (count != len)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ClientType NfsClient::clientType()
|
||||
{
|
||||
return CLIENT_TYPE_NFS;
|
||||
}
|
||||
|
||||
uint32_t NfsClient::SupportedActions()
|
||||
{
|
||||
return REMOTE_ACTION_ALL ^ REMOTE_ACTION_CUT ^ REMOTE_ACTION_COPY ^ REMOTE_ACTION_PASTE;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef NFSCLIENT_H
|
||||
#define NFSCLIENT_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "nfsc/libnfs.h"
|
||||
#include "nfsc/libnfs-raw.h"
|
||||
#include "nfsc/libnfs-raw-mount.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "common.h"
|
||||
|
||||
class NfsClient : public RemoteClient
|
||||
{
|
||||
public:
|
||||
NfsClient();
|
||||
~NfsClient();
|
||||
int Connect(const std::string &url, const std::string &user, const std::string &pass);
|
||||
int Mkdir(const std::string &path);
|
||||
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);
|
||||
bool FileExists(const std::string &path);
|
||||
int Copy(const std::string &from, const std::string &to);
|
||||
int Move(const std::string &from, const std::string &to);
|
||||
std::vector<DirEntry> ListDir(const std::string &path);
|
||||
bool IsConnected();
|
||||
bool Ping();
|
||||
const char *LastResponse();
|
||||
int Quit();
|
||||
std::string GetPath(std::string ppath1, std::string ppath2);
|
||||
int Head(const std::string &path, void *buffer, uint64_t len);
|
||||
ClientType clientType();
|
||||
uint32_t SupportedActions();
|
||||
|
||||
private:
|
||||
int _Rmdir(const std::string &ppath);
|
||||
struct nfs_context *nfs;
|
||||
char response[1024];
|
||||
bool connected = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -29,6 +29,7 @@ enum ClientType
|
||||
CLIENT_TYPE_WEBDAV,
|
||||
CLIENT_TYPE_HTTP_SERVER,
|
||||
CLIENT_TYPE_GOOGLE,
|
||||
CLIENT_TYPE_NFS,
|
||||
CLINET_TYPE_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
@@ -98,6 +98,10 @@ namespace CONFIG
|
||||
{
|
||||
setting->type = CLIENT_TYPE_HTTP_SERVER;
|
||||
}
|
||||
else if (strncmp(setting->server, "nfs://", 6) == 0)
|
||||
{
|
||||
setting->type = CLIENT_TYPE_NFS;
|
||||
}
|
||||
else
|
||||
{
|
||||
setting->type = CLINET_TYPE_UNKNOWN;
|
||||
|
||||
@@ -157,6 +157,9 @@ char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE] = {
|
||||
"has being set as default direcotry", // STR_SET_DEFAULT_DIRECTORY_MSG
|
||||
"View Image", // STR_VIEW_IMAGE
|
||||
"Package Information", // STR_VIEW_PKG_INFO
|
||||
"NFS export path missing in URL", // STR_NFS_EXP_PATH_MISSING_MSG
|
||||
"Failed to init NFS context", // STR_FAIL_INIT_NFS_CONTEXT
|
||||
"Failed to mount NFS share", // STR_FAIL_MOUNT_NFS_MSG
|
||||
};
|
||||
|
||||
bool needs_extended_font = false;
|
||||
|
||||
+5
-2
@@ -148,7 +148,10 @@
|
||||
FUNC(STR_SET_DEFAULT_DIRECTORY) \
|
||||
FUNC(STR_SET_DEFAULT_DIRECTORY_MSG) \
|
||||
FUNC(STR_VIEW_IMAGE) \
|
||||
FUNC(STR_VIEW_PKG_INFO)
|
||||
FUNC(STR_VIEW_PKG_INFO) \
|
||||
FUNC(STR_NFS_EXP_PATH_MISSING_MSG) \
|
||||
FUNC(STR_FAIL_INIT_NFS_CONTEXT) \
|
||||
FUNC(STR_FAIL_MOUNT_NFS_MSG)
|
||||
|
||||
#define GET_VALUE(x) x,
|
||||
#define GET_STRING(x) #x,
|
||||
@@ -158,7 +161,7 @@ enum
|
||||
FOREACH_STR(GET_VALUE)
|
||||
};
|
||||
|
||||
#define LANG_STRINGS_NUM 145
|
||||
#define LANG_STRINGS_NUM 148
|
||||
#define LANG_ID_SIZE 64
|
||||
#define LANG_STR_SIZE 384
|
||||
extern char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE];
|
||||
|
||||
+36
-28
@@ -342,6 +342,8 @@ namespace Windows
|
||||
width = 500;
|
||||
else if (remote_settings->type == CLIENT_TYPE_GOOGLE)
|
||||
width = 600;
|
||||
else if (remote_settings->type == CLIENT_TYPE_NFS)
|
||||
width = 900;
|
||||
pos = ImGui::GetCursorPos();
|
||||
if (ImGui::Button(id, ImVec2(width, 0)))
|
||||
{
|
||||
@@ -376,43 +378,49 @@ namespace Windows
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_USERNAME]);
|
||||
ImGui::SameLine();
|
||||
|
||||
width = 180;
|
||||
if (remote_settings->type == CLIENT_TYPE_GOOGLE)
|
||||
width = 480;
|
||||
sprintf(id, "%s##username", remote_settings->username);
|
||||
pos = ImGui::GetCursorPos();
|
||||
if (ImGui::Button(id, ImVec2(width, 0)))
|
||||
{
|
||||
ime_single_field = remote_settings->username;
|
||||
ResetImeCallbacks();
|
||||
ime_field_size = 32;
|
||||
ime_callback = SingleValueImeCallback;
|
||||
Dialog::initImeDialog(lang_strings[STR_USERNAME], remote_settings->username, 32, ORBIS_TYPE_BASIC_LATIN, pos.x, pos.y);
|
||||
gui_mode = GUI_MODE_IME;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
if (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::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_USERNAME]);
|
||||
ImGui::SameLine();
|
||||
|
||||
sprintf(id, "%s##password", hidden_password.c_str());
|
||||
width = 180;
|
||||
if (remote_settings->type == CLIENT_TYPE_GOOGLE)
|
||||
width = 480;
|
||||
sprintf(id, "%s##username", remote_settings->username);
|
||||
pos = ImGui::GetCursorPos();
|
||||
if (ImGui::Button(id, ImVec2(100, 0)))
|
||||
if (ImGui::Button(id, ImVec2(width, 0)))
|
||||
{
|
||||
ime_single_field = remote_settings->password;
|
||||
ime_single_field = remote_settings->username;
|
||||
ResetImeCallbacks();
|
||||
ime_field_size = 127;
|
||||
ime_field_size = 32;
|
||||
ime_callback = SingleValueImeCallback;
|
||||
Dialog::initImeDialog(lang_strings[STR_PASSWORD], remote_settings->password, 127, ORBIS_TYPE_BASIC_LATIN, pos.x, pos.y);
|
||||
Dialog::initImeDialog(lang_strings[STR_USERNAME], remote_settings->username, 32, ORBIS_TYPE_BASIC_LATIN, pos.x, pos.y);
|
||||
gui_mode = GUI_MODE_IME;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
if (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);
|
||||
@@ -433,7 +441,7 @@ namespace Windows
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
if ((remote_settings->type == CLIENT_TYPE_SMB || remote_settings->type == CLIENT_TYPE_FTP) && remote_settings->enable_rpi)
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user