mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-11 23:49:38 -05:00
Initial work on RsFiles links support in libretroshare
This commit is contained in:
parent
b6c5e2f188
commit
55d466f79b
@ -20,40 +20,89 @@
|
||||
* *
|
||||
******************************************************************************/
|
||||
#include <iomanip>
|
||||
#include <util/radix64.h>
|
||||
#include <util/rsdir.h>
|
||||
|
||||
#include "util/radix64.h"
|
||||
#include "util/rsdir.h"
|
||||
#include "retroshare/rsfiles.h"
|
||||
#include "file_sharing_defaults.h"
|
||||
#include "filelist_io.h"
|
||||
#include "file_tree.h"
|
||||
|
||||
std::string FileTreeImpl::toRadix64() const
|
||||
void RsFileTree::DirData::serial_process(
|
||||
RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
unsigned char *buff = NULL ;
|
||||
uint32_t size = 0 ;
|
||||
|
||||
serialise(buff,size) ;
|
||||
|
||||
std::string res ;
|
||||
|
||||
Radix64::encode(buff,size,res) ;
|
||||
|
||||
free(buff) ;
|
||||
return res ;
|
||||
RS_SERIAL_PROCESS(name);
|
||||
RS_SERIAL_PROCESS(subdirs);
|
||||
RS_SERIAL_PROCESS(subfiles);
|
||||
}
|
||||
|
||||
FileTree *FileTree::create(const std::string& radix64_string)
|
||||
void RsFileTree::FileData::serial_process(
|
||||
RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
FileTreeImpl *ft = new FileTreeImpl ;
|
||||
RS_SERIAL_PROCESS(name);
|
||||
RS_SERIAL_PROCESS(size);
|
||||
RS_SERIAL_PROCESS(hash);
|
||||
}
|
||||
|
||||
/*static*/ std::unique_ptr<RsFileTree> RsFileTree::fromBase64(
|
||||
const std::string& base64 )
|
||||
{
|
||||
std::unique_ptr<RsFileTree> ft(new RsFileTree);
|
||||
std::vector<uint8_t> mem = Radix64::decode(base64);
|
||||
RsGenericSerializer::SerializeContext ctx(
|
||||
mem.data(), static_cast<uint32_t>(mem.size()) );
|
||||
ft->serial_process(
|
||||
RsGenericSerializer::SerializeJob::DESERIALIZE, ctx);
|
||||
if(ctx.mOk) return ft;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string RsFileTree::toBase64() const
|
||||
{
|
||||
RsGenericSerializer::SerializeContext ctx;
|
||||
RsFileTree* ncThis = const_cast<RsFileTree*>(this);
|
||||
ncThis->serial_process(
|
||||
RsGenericSerializer::SerializeJob::SIZE_ESTIMATE, ctx );
|
||||
RsDbg() << __PRETTY_FUNCTION__ << " ctx.mOffset: " << ctx.mOffset
|
||||
<< std::endl;
|
||||
|
||||
std::vector<uint8_t> buf(ctx.mOffset);
|
||||
ctx.mSize = ctx.mOffset; ctx.mOffset = 0; ctx.mData = buf.data();
|
||||
|
||||
ncThis->serial_process(
|
||||
RsGenericSerializer::SerializeJob::SERIALIZE, ctx );
|
||||
std::string result;
|
||||
Radix64::encode(ctx.mData, ctx.mSize, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string RsFileTree::toRadix64() const
|
||||
{
|
||||
unsigned char* buff = nullptr;
|
||||
uint32_t size = 0;
|
||||
serialise(buff, size);
|
||||
std::string res;
|
||||
Radix64::encode(buff,size,res);
|
||||
free(buff);
|
||||
return res;
|
||||
}
|
||||
|
||||
std::unique_ptr<RsFileTree> RsFileTree::fromRadix64(
|
||||
const std::string& radix64_string )
|
||||
{
|
||||
std::unique_ptr<RsFileTree> ft(new RsFileTree);
|
||||
std::vector<uint8_t> mem = Radix64::decode(radix64_string);
|
||||
ft->deserialise(mem.data(),mem.size()) ;
|
||||
|
||||
return ft ;
|
||||
if(ft->deserialise(mem.data(), static_cast<uint32_t>(mem.size())))
|
||||
return std::move(ft);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FileTreeImpl::recurs_buildFileTree(FileTreeImpl& ft,uint32_t index,const DirDetails& dd,bool remote,bool remove_top_dirs)
|
||||
void RsFileTree::recurs_buildFileTree(
|
||||
RsFileTree& ft, uint32_t index, const DirDetails& dd, bool remote,
|
||||
bool remove_top_dirs )
|
||||
{
|
||||
RsDbg() << __PRETTY_FUNCTION__ << " index: " << index << std::endl;
|
||||
if(ft.mDirs.size() <= index)
|
||||
ft.mDirs.resize(index+1) ;
|
||||
|
||||
@ -67,14 +116,14 @@ void FileTreeImpl::recurs_buildFileTree(FileTreeImpl& ft,uint32_t index,const Di
|
||||
|
||||
DirDetails dd2 ;
|
||||
|
||||
FileSearchFlags flags = remote?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ;
|
||||
FileSearchFlags flags = remote ? RS_FILE_HINTS_REMOTE : RS_FILE_HINTS_LOCAL;
|
||||
|
||||
for(uint32_t i=0;i<dd.children.size();++i)
|
||||
if(rsFiles->RequestDirDetails(dd.children[i].ref,dd2,flags))
|
||||
{
|
||||
if(dd.children[i].type == DIR_TYPE_FILE)
|
||||
{
|
||||
FileTree::FileData f ;
|
||||
FileData f ;
|
||||
f.name = dd2.name ;
|
||||
f.size = dd2.count ;
|
||||
f.hash = dd2.hash ;
|
||||
@ -97,7 +146,9 @@ void FileTreeImpl::recurs_buildFileTree(FileTreeImpl& ft,uint32_t index,const Di
|
||||
std::cerr << "(EE) Cannot request dir details for pointer " << dd.children[i].ref << std::endl;
|
||||
}
|
||||
|
||||
bool FileTreeImpl::getDirectoryContent(uint32_t index,std::string& name,std::vector<uint32_t>& subdirs,std::vector<FileData>& subfiles) const
|
||||
bool RsFileTree::getDirectoryContent(
|
||||
std::string& name, std::vector<std::uintptr_t>& subdirs,
|
||||
std::vector<FileData>& subfiles, std::uintptr_t index ) const
|
||||
{
|
||||
if(index >= mDirs.size())
|
||||
return false ;
|
||||
@ -112,18 +163,25 @@ bool FileTreeImpl::getDirectoryContent(uint32_t index,std::string& name,std::vec
|
||||
return true ;
|
||||
}
|
||||
|
||||
FileTree *FileTree::create(const DirDetails& dd, bool remote,bool remove_top_dirs)
|
||||
std::unique_ptr<RsFileTree> RsFileTree::fromDirDetails(
|
||||
const DirDetails& dd, bool remote ,bool remove_top_dirs )
|
||||
{
|
||||
FileTreeImpl *ft = new FileTreeImpl ;
|
||||
|
||||
FileTreeImpl::recurs_buildFileTree(*ft,0,dd,remote,remove_top_dirs) ;
|
||||
|
||||
return ft ;
|
||||
std::unique_ptr<RsFileTree>ft(new RsFileTree);
|
||||
if(dd.type == DIR_TYPE_FILE)
|
||||
{
|
||||
FileData fd;
|
||||
fd.name = dd.name; fd.hash = dd.hash; fd.size = dd.count;
|
||||
ft->mFiles.push_back(fd);
|
||||
ft->mTotalFiles = 1;
|
||||
ft->mTotalSize = fd.size;
|
||||
}
|
||||
else recurs_buildFileTree(*ft, 0, dd, remote, remove_top_dirs );
|
||||
return ft;
|
||||
}
|
||||
|
||||
typedef FileListIO::read_error read_error ;
|
||||
|
||||
bool FileTreeImpl::deserialise(unsigned char *buffer,uint32_t buffer_size)
|
||||
bool RsFileTree::deserialise(unsigned char *buffer,uint32_t buffer_size)
|
||||
{
|
||||
uint32_t buffer_offset = 0 ;
|
||||
|
||||
@ -218,7 +276,7 @@ bool FileTreeImpl::deserialise(unsigned char *buffer,uint32_t buffer_size)
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool FileTreeImpl::serialise(unsigned char *& buffer,uint32_t& buffer_size) const
|
||||
bool RsFileTree::serialise(unsigned char *& buffer,uint32_t& buffer_size) const
|
||||
{
|
||||
buffer = 0 ;
|
||||
uint32_t buffer_offset = 0 ;
|
||||
@ -234,7 +292,11 @@ bool FileTreeImpl::serialise(unsigned char *& buffer,uint32_t& buffer_size) cons
|
||||
{
|
||||
// Write some header
|
||||
|
||||
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION,(uint32_t) FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001)) throw std::runtime_error("Write error") ;
|
||||
if(!FileListIO::writeField(
|
||||
buffer, buffer_size, buffer_offset,
|
||||
FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION,
|
||||
(uint32_t) FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001 ) )
|
||||
throw std::runtime_error("Write error") ;
|
||||
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t) mFiles.size())) throw std::runtime_error("Write error") ;
|
||||
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t) mDirs.size())) throw std::runtime_error("Write error") ;
|
||||
|
||||
@ -291,29 +353,3 @@ bool FileTreeImpl::serialise(unsigned char *& buffer,uint32_t& buffer_size) cons
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void FileTreeImpl::print() const
|
||||
{
|
||||
std::cerr << "File hierarchy: name=" << mDirs[0].name << " size=" << mTotalSize << std::endl;
|
||||
recurs_print(0," ") ;
|
||||
}
|
||||
|
||||
void FileTreeImpl::recurs_print(uint32_t index,const std::string& indent) const
|
||||
{
|
||||
if(index >= mDirs.size())
|
||||
{
|
||||
std::cerr << "(EE) inconsistent FileTree structure" << std::endl;
|
||||
return;
|
||||
}
|
||||
std::cerr << indent << mDirs[index].name << std::endl;
|
||||
|
||||
for(uint32_t i=0;i<mDirs[index].subdirs.size();++i)
|
||||
recurs_print(mDirs[index].subdirs[i],indent+" ") ;
|
||||
|
||||
for(uint32_t i=0;i<mDirs[index].subfiles.size();++i)
|
||||
{
|
||||
const FileData& fd(mFiles[mDirs[index].subfiles[i]]) ;
|
||||
|
||||
std::cerr << indent << " " << fd.hash << " " << std::setprecision(8) << fd.size << " " << fd.name << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* libretroshare/src/file_sharing: file_tree.h *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2018 by Cyril Soler <csoler@users.sourceforge.net> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
#include "retroshare/rsfiles.h"
|
||||
|
||||
class FileTreeImpl: public FileTree
|
||||
{
|
||||
public:
|
||||
FileTreeImpl()
|
||||
{
|
||||
mTotalFiles = 0 ;
|
||||
mTotalSize = 0 ;
|
||||
}
|
||||
|
||||
virtual std::string toRadix64() const ;
|
||||
virtual bool getDirectoryContent(uint32_t index,std::string& name,std::vector<uint32_t>& subdirs,std::vector<FileData>& subfiles) const ;
|
||||
virtual void print() const ;
|
||||
|
||||
bool serialise(unsigned char *& data,uint32_t& data_size) const ;
|
||||
bool deserialise(unsigned char* data, uint32_t data_size) ;
|
||||
|
||||
protected:
|
||||
void recurs_print(uint32_t index,const std::string& indent) const;
|
||||
|
||||
static void recurs_buildFileTree(FileTreeImpl& ft, uint32_t index, const DirDetails& dd, bool remote, bool remove_top_dirs);
|
||||
|
||||
struct DirData {
|
||||
std::string name;
|
||||
std::vector<uint32_t> subdirs ;
|
||||
std::vector<uint32_t> subfiles ;
|
||||
};
|
||||
std::vector<FileData> mFiles ;
|
||||
std::vector<DirData> mDirs ;
|
||||
|
||||
friend class FileTree ;
|
||||
};
|
@ -43,10 +43,10 @@
|
||||
|
||||
#include "rsitems/rsfiletransferitems.h"
|
||||
#include "rsitems/rsserviceids.h"
|
||||
|
||||
#include "util/rsmemory.h"
|
||||
#include "rsserver/p3face.h"
|
||||
#include "turtle/p3turtle.h"
|
||||
|
||||
#include "util/rsurl.h"
|
||||
#include "util/rsdebug.h"
|
||||
#include "util/rsdir.h"
|
||||
#include "util/rsprint.h"
|
||||
@ -66,6 +66,16 @@
|
||||
#define FTSERVER_DEBUG() std::cerr << time(NULL) << " : FILE_SERVER : " << __FUNCTION__ << " : "
|
||||
#define FTSERVER_ERROR() std::cerr << "(EE) FILE_SERVER ERROR : "
|
||||
|
||||
/*static*/ const RsFilesErrorCategory RsFilesErrorCategory::instance;
|
||||
|
||||
/*static*/ const std::string RsFiles::DEFAULT_FILES_BASE_URL =
|
||||
"retroshare:///files";
|
||||
/*static*/ const std::string RsFiles::FILES_URL_COUNT_FIELD = "filesCount";
|
||||
/*static*/ const std::string RsFiles::FILES_URL_DATA_FIELD = "filesData";
|
||||
/*static*/ const std::string RsFiles::FILES_URL_NAME_FIELD = "filesName";
|
||||
/*static*/ const std::string RsFiles::FILES_URL_SIZE_FIELD = "filesSize";
|
||||
|
||||
|
||||
static const rstime_t FILE_TRANSFER_LOW_PRIORITY_TASKS_PERIOD = 5 ; // low priority tasks handling every 5 seconds
|
||||
static const rstime_t FILE_TRANSFER_MAX_DELAY_BEFORE_DROP_USAGE_RECORD = 10 ; // keep usage records for 10 secs at most.
|
||||
|
||||
@ -2101,3 +2111,62 @@ RsFileItem::RsFileItem(RsFileItemType subtype) :
|
||||
void RsFileSearchRequestItem::clear() { queryString.clear(); }
|
||||
|
||||
void RsFileSearchResultItem::clear() { mResults.clear(); }
|
||||
|
||||
|
||||
std::error_condition RsFilesErrorCategory::default_error_condition(int ev)
|
||||
const noexcept
|
||||
{
|
||||
switch(static_cast<RsFilesErrorNum>(ev))
|
||||
{
|
||||
case RsFilesErrorNum::FILES_HANDLE_NOT_FOUND: // [[fallthrough]];
|
||||
case RsFilesErrorNum::INVALID_FILES_URL:
|
||||
return std::errc::invalid_argument;
|
||||
default:
|
||||
return std::error_condition(ev, *this);
|
||||
}
|
||||
}
|
||||
|
||||
std::error_condition ftServer::exportFilesLink(
|
||||
std::string& link, std::uintptr_t handle, const std::string& baseUrl )
|
||||
{
|
||||
DirDetails tDirDet;
|
||||
if(!requestDirDetails(tDirDet, handle))
|
||||
return RsFilesErrorNum::FILES_HANDLE_NOT_FOUND;
|
||||
|
||||
std::unique_ptr<RsFileTree> tFileTree =
|
||||
RsFileTree::fromDirDetails(tDirDet, false);
|
||||
link = tFileTree->toBase64();
|
||||
|
||||
if(!baseUrl.empty())
|
||||
{
|
||||
RsUrl tUrl(baseUrl);
|
||||
tUrl.setQueryKV(FILES_URL_COUNT_FIELD,
|
||||
std::to_string(tFileTree->mTotalFiles) )
|
||||
.setQueryKV(FILES_URL_DATA_FIELD, link)
|
||||
.setQueryKV(FILES_URL_NAME_FIELD, tDirDet.name)
|
||||
.setQueryKV( FILES_URL_SIZE_FIELD,
|
||||
std::to_string(tFileTree->mTotalSize) );
|
||||
link = tUrl.toString();
|
||||
}
|
||||
|
||||
return std::error_condition();
|
||||
}
|
||||
|
||||
std::error_condition ftServer::parseFilesLink(
|
||||
const std::string& link, RsFileTree& collection )
|
||||
{
|
||||
RsUrl tUrl(link);
|
||||
rs_view_ptr<const std::string> radixPtr =
|
||||
tUrl.getQueryV(FILES_URL_DATA_FIELD);
|
||||
if(!radixPtr) radixPtr = &link;
|
||||
|
||||
std::unique_ptr<RsFileTree> tft =
|
||||
RsFileTree::fromBase64(*radixPtr);
|
||||
if(tft)
|
||||
{
|
||||
collection = *tft;
|
||||
return std::error_condition();
|
||||
}
|
||||
|
||||
return RsFilesErrorNum::INVALID_FILES_URL;
|
||||
}
|
||||
|
@ -207,14 +207,24 @@ public:
|
||||
virtual uint32_t filePermDirectDL() ;
|
||||
|
||||
/// @see RsFiles
|
||||
virtual bool turtleSearchRequest(
|
||||
bool turtleSearchRequest(
|
||||
const std::string& matchString,
|
||||
const std::function<void (const std::vector<TurtleFileInfoV2>& results)>& multiCallback,
|
||||
rstime_t maxWait = 300 );
|
||||
rstime_t maxWait = 300 ) override;
|
||||
|
||||
virtual TurtleSearchRequestId turtleSearch(const std::string& string_to_match) ;
|
||||
virtual TurtleSearchRequestId turtleSearch(const RsRegularExpression::LinearizedExpression& expr) ;
|
||||
|
||||
/// @see RsFiles
|
||||
std::error_condition exportFilesLink(
|
||||
std::string& link, std::uintptr_t handle,
|
||||
const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL
|
||||
) override;
|
||||
|
||||
/// @see RsFiles
|
||||
std::error_condition parseFilesLink(
|
||||
const std::string& link, RsFileTree& collection ) override;
|
||||
|
||||
/***
|
||||
* Control of Downloads Priority.
|
||||
***/
|
||||
|
@ -45,7 +45,6 @@ file_lists {
|
||||
file_sharing/directory_updater.h \
|
||||
file_sharing/rsfilelistitems.h \
|
||||
file_sharing/dir_hierarchy.h \
|
||||
file_sharing/file_tree.h \
|
||||
file_sharing/file_sharing_defaults.h
|
||||
|
||||
SOURCES *= file_sharing/p3filelists.cc \
|
||||
|
@ -28,12 +28,14 @@
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <system_error>
|
||||
|
||||
#include "rstypes.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
#include "rsturtle.h"
|
||||
#include "util/rstime.h"
|
||||
#include "retroshare/rsevents.h"
|
||||
#include "util/rsmemory.h"
|
||||
|
||||
class RsFiles;
|
||||
|
||||
@ -43,6 +45,53 @@ class RsFiles;
|
||||
*/
|
||||
extern RsFiles* rsFiles;
|
||||
|
||||
enum class RsFilesErrorNum : int32_t
|
||||
{
|
||||
FILES_HANDLE_NOT_FOUND = 2004,
|
||||
INVALID_FILES_URL = 2005
|
||||
};
|
||||
|
||||
struct RsFilesErrorCategory: std::error_category
|
||||
{
|
||||
const char* name() const noexcept override
|
||||
{ return "RetroShare Files"; }
|
||||
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<RsFilesErrorNum>(ev))
|
||||
{
|
||||
case RsFilesErrorNum::FILES_HANDLE_NOT_FOUND:
|
||||
return "Files handle not found";
|
||||
case RsFilesErrorNum::INVALID_FILES_URL:
|
||||
return "Invalid files url";
|
||||
default:
|
||||
return "Error message for error: " + std::to_string(ev) +
|
||||
" not available in category: " + name();
|
||||
}
|
||||
}
|
||||
|
||||
std::error_condition default_error_condition(int ev) const noexcept override;
|
||||
|
||||
const static RsFilesErrorCategory instance;
|
||||
};
|
||||
|
||||
|
||||
namespace std
|
||||
{
|
||||
/** Register RsFilesErrorNum as an error condition enum, must be in std
|
||||
* namespace */
|
||||
template<> struct is_error_condition_enum<RsFilesErrorNum> : true_type {};
|
||||
}
|
||||
|
||||
/** Provide RsJsonApiErrorNum conversion to std::error_condition, must be in
|
||||
* same namespace of RsJsonApiErrorNum */
|
||||
inline std::error_condition make_error_condition(RsFilesErrorNum e) noexcept
|
||||
{
|
||||
return std::error_condition(
|
||||
static_cast<int>(e), RsFilesErrorCategory::instance );
|
||||
};
|
||||
|
||||
|
||||
namespace RsRegularExpression { class Expression; }
|
||||
|
||||
/* These are used mainly by ftController at the moment */
|
||||
@ -96,8 +145,28 @@ const FileSearchFlags RS_FILE_HINTS_BROWSABLE ( 0x00000100 );// bro
|
||||
const FileSearchFlags RS_FILE_HINTS_SEARCHABLE ( 0x00000200 );// can be searched anonymously
|
||||
const FileSearchFlags RS_FILE_HINTS_PERMISSION_MASK ( 0x00000380 );// OR of the last tree flags. Used to filter out.
|
||||
|
||||
// Flags used when requesting a transfer
|
||||
//
|
||||
/** Flags used when requesting a new file transfer */
|
||||
enum class FileRequestFlags: uint32_t
|
||||
{
|
||||
/// Enable requesting file via turtle routing.
|
||||
ANONYMOUS_ROUTING = 0x00000040,
|
||||
|
||||
/// Asks (TODO: or enforce?) for end-to-end encryption of file trasfer
|
||||
ENCRYPTED = 0x00000080,
|
||||
|
||||
/// Asks (TODO: or enforce?) no end-to-end encryption of file trasfer
|
||||
UNENCRYPTED = 0x00000100,
|
||||
|
||||
/// Start trasfer very slow
|
||||
SLOW = 0x00002000,
|
||||
|
||||
/// Disable searching for potential direct sources
|
||||
NO_DIRECT_SEARCH = 0x02000000
|
||||
};
|
||||
RS_REGISTER_ENUM_FLAGS_TYPE(FileRequestFlags)
|
||||
|
||||
/// @deprecated Flags used when requesting a transfer
|
||||
/// @see FileRequestFlags instead
|
||||
const TransferRequestFlags RS_FILE_REQ_ANONYMOUS_ROUTING ( 0x00000040 ); // Use to ask turtle router to download the file.
|
||||
const TransferRequestFlags RS_FILE_REQ_ENCRYPTED ( 0x00000080 ); // Asks for end-to-end encryption of file at the level of ftServer
|
||||
const TransferRequestFlags RS_FILE_REQ_UNENCRYPTED ( 0x00000100 ); // Asks for no end-to-end encryption of file at the level of ftServer
|
||||
@ -202,36 +271,119 @@ struct SharedDirStats
|
||||
uint64_t total_shared_size ;
|
||||
};
|
||||
|
||||
// This class represents a tree of directories and files, only with their names size and hash. It is used to create collection links in the GUI
|
||||
// and to transmit directory information between services. This class is independent from the existing FileHierarchy classes used in storage because
|
||||
// we need a very copact serialization and storage size since we create links with it. Besides, we cannot afford to risk the leak of other local information
|
||||
// by using the orignal classes.
|
||||
|
||||
class FileTree
|
||||
/** This class represents a tree of directories and files, only with their names
|
||||
* size and hash. It is used to create collection links in the GUI and to
|
||||
* transmit directory information between services. This class is independent
|
||||
* from the existing FileHierarchy classes used in storage because we need a
|
||||
* very copact serialization and storage size since we create links with it.
|
||||
* Besides, we cannot afford to risk the leak of other local information
|
||||
* by using the orignal classes.
|
||||
*/
|
||||
struct RsFileTree : RsSerializable
|
||||
{
|
||||
public:
|
||||
virtual ~FileTree() {}
|
||||
RsFileTree() : mTotalFiles(0), mTotalSize(0) {}
|
||||
|
||||
static FileTree *create(const DirDetails& dd, bool remote, bool remove_top_dirs = true) ;
|
||||
static FileTree *create(const std::string& radix64_string) ;
|
||||
/**
|
||||
* @brief Create a RsFileTree from directory details
|
||||
* @param dd
|
||||
* @param remote
|
||||
* @param remove_top_dirs
|
||||
* @return
|
||||
*/
|
||||
static std::unique_ptr<RsFileTree> fromDirDetails(
|
||||
const DirDetails& dd, bool remote, bool remove_top_dirs = true );
|
||||
|
||||
virtual std::string toRadix64() const =0 ;
|
||||
/**
|
||||
* @brief Create a RsFileTree from Radix64 representation
|
||||
* @param base64
|
||||
* @return nullptr if on failure, pointer to the created FileTree on success
|
||||
*/
|
||||
static std::unique_ptr<RsFileTree> fromBase64(
|
||||
const std::string& base64 );
|
||||
|
||||
// These methods allow the user to browse the hierarchy
|
||||
/** @brief Convert to base64 representetion */
|
||||
std::string toBase64() const;
|
||||
|
||||
struct FileData {
|
||||
std::string name ;
|
||||
uint64_t size ;
|
||||
RsFileHash hash ;
|
||||
/// @see RsSerializable
|
||||
virtual void serial_process(
|
||||
RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
/* TODO: most of the time handles are smaller then 64bit use VLQ for
|
||||
* binary serialization of those
|
||||
* https://en.wikipedia.org/wiki/Variable-length_quantity#Zigzag_encoding
|
||||
*/
|
||||
RS_SERIAL_PROCESS(mFiles);
|
||||
RS_SERIAL_PROCESS(mDirs);
|
||||
RS_SERIAL_PROCESS(mTotalFiles);
|
||||
RS_SERIAL_PROCESS(mTotalSize);
|
||||
}
|
||||
|
||||
struct FileData: RsSerializable
|
||||
{
|
||||
std::string name;
|
||||
uint64_t size;
|
||||
RsFileHash hash;
|
||||
|
||||
void serial_process(
|
||||
RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx ) override;
|
||||
};
|
||||
|
||||
virtual uint32_t root() const { return 0;}
|
||||
virtual bool getDirectoryContent(uint32_t index,std::string& name,std::vector<uint32_t>& subdirs,std::vector<FileData>& subfiles) const = 0;
|
||||
/// Allow browsing the hierarchy
|
||||
bool getDirectoryContent(
|
||||
std::string& name, std::vector<std::uintptr_t>& subdirs,
|
||||
std::vector<FileData>& subfiles, std::uintptr_t handle = 0 ) const;
|
||||
|
||||
virtual void print() const=0;
|
||||
struct DirData: RsSerializable
|
||||
{
|
||||
std::string name;
|
||||
std::vector<std::uintptr_t> subdirs;
|
||||
std::vector<std::uintptr_t> subfiles;
|
||||
|
||||
uint32_t mTotalFiles ;
|
||||
uint64_t mTotalSize ;
|
||||
void serial_process(
|
||||
RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx ) override;
|
||||
};
|
||||
|
||||
static void recurs_buildFileTree(
|
||||
RsFileTree& ft, uint32_t index, const DirDetails& dd, bool remote,
|
||||
bool remove_top_dirs );
|
||||
|
||||
std::vector<FileData> mFiles;
|
||||
std::vector<DirData> mDirs;
|
||||
|
||||
uint32_t mTotalFiles;
|
||||
uint64_t mTotalSize;
|
||||
|
||||
~RsFileTree() = default;
|
||||
|
||||
/**
|
||||
* @brief Create a RsFileTree from Radix64 representation
|
||||
* @deprecated kept for retrocompatibility with RetroShare-gui
|
||||
* The format is not guardanted to be compatible with the new methods
|
||||
* @param radix64_string
|
||||
* @return nullptr if on failure, pointer to the created FileTree on success
|
||||
*/
|
||||
RS_DEPRECATED
|
||||
static std::unique_ptr<RsFileTree> fromRadix64(
|
||||
const std::string& radix64_string );
|
||||
|
||||
/** @brief Convert to radix64 representetion
|
||||
* @deprecated kept for retrocompatibility with RetroShare-gui
|
||||
* The format is not guardanted to be compatible with the new methods
|
||||
*/
|
||||
RS_DEPRECATED std::string toRadix64() const;
|
||||
|
||||
private:
|
||||
/** @deprecated kept for retrocompatibility with RetroShare-gui */
|
||||
RS_DEPRECATED_FOR(serial_process)
|
||||
bool serialise(unsigned char *& data,uint32_t& data_size) const;
|
||||
|
||||
/** @deprecated kept for retrocompatibility with RetroShare-gui */
|
||||
RS_DEPRECATED_FOR(serial_process)
|
||||
bool deserialise(unsigned char* data, uint32_t data_size);
|
||||
};
|
||||
|
||||
struct BannedFileEntry : RsSerializable
|
||||
@ -301,9 +453,6 @@ struct TurtleFileInfoV2 : RsSerializable
|
||||
class RsFiles
|
||||
{
|
||||
public:
|
||||
RsFiles() {}
|
||||
virtual ~RsFiles() {}
|
||||
|
||||
/**
|
||||
* @brief Provides file data for the GUI, media streaming or API clients.
|
||||
* It may return unverified chunks. This allows streaming without having to
|
||||
@ -726,6 +875,50 @@ public:
|
||||
*/
|
||||
virtual bool removeSharedDirectory(std::string dir) = 0;
|
||||
|
||||
/// Default base URL used for files links @see exportFilesLink
|
||||
static const std::string DEFAULT_FILES_BASE_URL;
|
||||
|
||||
/** Link query field used to store collection files count
|
||||
* @see exportFilesLink */
|
||||
static const std::string FILES_URL_COUNT_FIELD;
|
||||
|
||||
/// Link query field used to store collection data @see exportFilesLink
|
||||
static const std::string FILES_URL_DATA_FIELD;
|
||||
|
||||
/// Link query field used to store collection name @see exportFilesLink
|
||||
static const std::string FILES_URL_NAME_FIELD;
|
||||
|
||||
/// Link query field used to store collection size @see exportFilesLink
|
||||
static const std::string FILES_URL_SIZE_FIELD;
|
||||
|
||||
/**
|
||||
* @brief Get link to a forum
|
||||
* @jsonapi{development}
|
||||
* @param[out] link storage for the generated link
|
||||
* @param[in] handle file/directory RetroShare handle
|
||||
* @param[in] baseUrl URL into which to sneak in the RetroShare link
|
||||
* radix, this is primarly useful to induce applications into making the
|
||||
* link clickable, or to disguise the RetroShare link into a
|
||||
* "normal" looking web link. If empty the collection data link will be
|
||||
* outputted in plain base64 format.
|
||||
* @return error information if some error occurred, 0/SUCCESS otherwise
|
||||
*/
|
||||
virtual std::error_condition exportFilesLink(
|
||||
std::string& link, std::uintptr_t handle,
|
||||
const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Parse RetroShare files link
|
||||
* @jsonapi{development}
|
||||
* @param[in] link files link either in radix or URL format
|
||||
* @param[out] collection optional storage for parsed files link
|
||||
* @return error information if some error occurred, 0/SUCCESS otherwise
|
||||
*/
|
||||
virtual std::error_condition parseFilesLink(
|
||||
const std::string& link, RsFileTree& collection ) = 0;
|
||||
|
||||
// virtual std::error_condition downloadFilesLink(FileRequestFlags)
|
||||
|
||||
/**
|
||||
* @brief Get list of ignored file name prefixes and suffixes
|
||||
* @param[out] ignoredPrefixes storage for ingored prefixes
|
||||
@ -757,4 +950,6 @@ public:
|
||||
|
||||
virtual bool ignoreDuplicates() = 0;
|
||||
virtual void setIgnoreDuplicates(bool ignore) = 0;
|
||||
|
||||
virtual ~RsFiles() = default;
|
||||
};
|
||||
|
@ -210,9 +210,9 @@ template<int n> class RS_DEPRECATED_FOR(RS_REGISTER_ENUM_FLAGS_TYPE) t_RsFlags32
|
||||
#define FLAGS_TAG_SERVICE_CHAT 0x839042
|
||||
#define FLAGS_TAG_SERIALIZER 0xa0338d
|
||||
|
||||
// Flags for requesting transfers, ask for turtle, cache, speed, etc.
|
||||
//
|
||||
typedef t_RsFlags32<FLAGS_TAG_TRANSFER_REQS> TransferRequestFlags ;
|
||||
/// @deprecated Flags for requesting transfers, ask for turtle, cache, speed, etc.
|
||||
RS_DEPRECATED_FOR(FileRequestFlags)
|
||||
typedef t_RsFlags32<FLAGS_TAG_TRANSFER_REQS> TransferRequestFlags;
|
||||
|
||||
// Flags for file storage. Mainly permissions like BROWSABLE/NETWORK_WIDE for groups and peers.
|
||||
//
|
||||
|
@ -305,10 +305,10 @@ public:
|
||||
static const std::string FORUM_URL_DATA_FIELD;
|
||||
|
||||
/** Link query field used to store forum message title
|
||||
* @see exportChannelLink */
|
||||
* @see exportForumLink */
|
||||
static const std::string FORUM_URL_MSG_TITLE_FIELD;
|
||||
|
||||
/// Link query field used to store forum message id @see exportChannelLink
|
||||
/// Link query field used to store forum message id @see exportForumLink
|
||||
static const std::string FORUM_URL_MSG_ID_FIELD;
|
||||
|
||||
/**
|
||||
|
@ -62,7 +62,6 @@ bool myFunnyFunction(
|
||||
*/
|
||||
#define RS_DEFAULT_STORAGE_PARAM(Type,...) *std::unique_ptr<Type>(new Type(__VA_ARGS__))
|
||||
|
||||
|
||||
/** @brief Safely dynamic cast between std::unique_ptr of different types
|
||||
* std::unique_ptr semantic rely on the invariant that only one instance own
|
||||
* the object, when casting between differents types one would be tempted to do
|
||||
@ -90,6 +89,16 @@ bool rs_unique_cast(
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Mark a pointer as non-owned aka you are not in charge of deleting it and
|
||||
* must not delete it.
|
||||
* @see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1408r0.pdf */
|
||||
template<typename T> using rs_view_ptr = T*;
|
||||
|
||||
/** Mark a pointer as owned aka you are in charge of deletingonce finished
|
||||
* dealing with it.
|
||||
* @see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1408r0.pdf */
|
||||
template<typename T> using rs_owner_ptr = T*;
|
||||
|
||||
|
||||
void *rs_malloc(size_t size) ;
|
||||
|
||||
|
@ -224,7 +224,7 @@ RsUrl& RsUrl::delQueryK(const std::string& key)
|
||||
}
|
||||
bool RsUrl::hasQueryK(const std::string& key)
|
||||
{ return (mQuery.find(key) != mQuery.end()); }
|
||||
const std::string* RsUrl::getQueryV(const std::string& key)
|
||||
rs_view_ptr<const std::string> RsUrl::getQueryV(const std::string& key)
|
||||
{
|
||||
if(hasQueryK(key)) return &(mQuery.find(key)->second);
|
||||
return nullptr;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "util/rsmemory.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
|
||||
struct sockaddr_storage;
|
||||
@ -63,7 +64,7 @@ struct RsUrl : RsSerializable
|
||||
RsUrl& setQueryKV(const std::string& key, const std::string& value);
|
||||
RsUrl& delQueryK(const std::string& key);
|
||||
bool hasQueryK(const std::string& key);
|
||||
const std::string* getQueryV(const std::string& key);
|
||||
rs_view_ptr<const std::string> getQueryV(const std::string& key);
|
||||
|
||||
const std::string& fragment() const;
|
||||
RsUrl& setFragment(const std::string& fragment);
|
||||
|
@ -623,10 +623,7 @@ void SharedFilesDialog::copyLinks(const QModelIndexList& lst, bool remote,QList<
|
||||
|
||||
if (details.type == DIR_TYPE_DIR)
|
||||
{
|
||||
FileTree *ft = FileTree::create(details,remote) ;
|
||||
|
||||
std::cerr << "Created collection file tree:" << std::endl;
|
||||
ft->print();
|
||||
auto ft = RsFileTree::fromDirDetails(details,remote);
|
||||
|
||||
QString dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName();
|
||||
|
||||
@ -634,8 +631,6 @@ void SharedFilesDialog::copyLinks(const QModelIndexList& lst, bool remote,QList<
|
||||
|
||||
if(link.valid())
|
||||
urls.push_back(link) ;
|
||||
|
||||
delete ft ;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2225,9 +2225,8 @@ void TransfersDialog::pasteLink()
|
||||
|
||||
for(QList<RetroShareLink>::const_iterator it(links.begin());it!=links.end();++it)
|
||||
{
|
||||
FileTree *ft = FileTree::create((*it).radix().toStdString()) ;
|
||||
|
||||
col.merge_in(*ft) ;
|
||||
auto ft = RsFileTree::fromRadix64((*it).radix().toStdString());
|
||||
col.merge_in(*ft);
|
||||
}
|
||||
links.clear();
|
||||
RSLinkClipboard::pasteLinks(links,RetroShareLink::TYPE_FILE);
|
||||
|
@ -1706,15 +1706,13 @@ static void processList(const QStringList &list, const QString &textSingular, co
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_FILE_TREE:
|
||||
{
|
||||
FileTree *ft = FileTree::create(link.radix().toStdString()) ;
|
||||
|
||||
RsCollection(*ft).downloadFiles() ;
|
||||
|
||||
delete ft;
|
||||
}
|
||||
case TYPE_FILE_TREE:
|
||||
{
|
||||
auto ft = RsFileTree::fromRadix64(
|
||||
link.radix().toStdString() );
|
||||
RsCollection(*ft).downloadFiles();
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_CHAT_ROOM:
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ RsCollection::RsCollection(QObject *parent)
|
||||
_xml_doc.appendChild(_root);
|
||||
}
|
||||
|
||||
RsCollection::RsCollection(const FileTree& fr)
|
||||
RsCollection::RsCollection(const RsFileTree& fr)
|
||||
: _xml_doc("RsCollection")
|
||||
{
|
||||
_root = _xml_doc.createElement("RsCollection");
|
||||
@ -153,7 +153,7 @@ void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash&
|
||||
|
||||
recursAddElements(_xml_doc,info,_root) ;
|
||||
}
|
||||
void RsCollection::merge_in(const FileTree& tree)
|
||||
void RsCollection::merge_in(const RsFileTree& tree)
|
||||
{
|
||||
recursAddElements(_xml_doc,tree,0,_root) ;
|
||||
}
|
||||
@ -273,14 +273,14 @@ void RsCollection::recursAddElements(QDomDocument& doc,const ColFileInfo& colFil
|
||||
}
|
||||
}
|
||||
|
||||
void RsCollection::recursAddElements(QDomDocument& doc,const FileTree& ft,uint32_t index,QDomElement& e) const
|
||||
void RsCollection::recursAddElements(
|
||||
QDomDocument& doc, const RsFileTree& ft, uint32_t index,
|
||||
QDomElement& e ) const
|
||||
{
|
||||
std::vector<uint32_t> subdirs ;
|
||||
std::vector<FileTree::FileData> subfiles ;
|
||||
std::vector<std::uintptr_t> subdirs;
|
||||
std::vector<RsFileTree::FileData> subfiles ;
|
||||
std::string name;
|
||||
|
||||
if(!ft.getDirectoryContent(index,name,subdirs,subfiles))
|
||||
return ;
|
||||
if(!ft.getDirectoryContent(name, subdirs, subfiles, index)) return;
|
||||
|
||||
QDomElement d = doc.createElement("Directory") ;
|
||||
d.setAttribute(QString("name"),QString::fromUtf8(name.c_str())) ;
|
||||
|
@ -62,11 +62,11 @@ public:
|
||||
RsCollection(QObject *parent = 0) ;
|
||||
// create from list of files and directories
|
||||
RsCollection(const std::vector<DirDetails>& file_entries, FileSearchFlags flags, QObject *parent = 0) ;
|
||||
RsCollection(const FileTree& fr);
|
||||
RsCollection(const RsFileTree& fr);
|
||||
virtual ~RsCollection() ;
|
||||
|
||||
void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) ;
|
||||
void merge_in(const FileTree& tree) ;
|
||||
void merge_in(const RsFileTree& tree) ;
|
||||
|
||||
static const QString ExtensionString ;
|
||||
|
||||
@ -99,7 +99,9 @@ private:
|
||||
|
||||
void recursAddElements(QDomDocument&, const DirDetails&, QDomElement&, FileSearchFlags flags) const ;
|
||||
void recursAddElements(QDomDocument&,const ColFileInfo&,QDomElement&) const;
|
||||
void recursAddElements(QDomDocument& doc,const FileTree& ft,uint32_t index,QDomElement& e) const;
|
||||
void recursAddElements(
|
||||
QDomDocument& doc, const RsFileTree& ft, uint32_t index,
|
||||
QDomElement& e ) const;
|
||||
|
||||
void recursCollectColFileInfos(const QDomElement&,std::vector<ColFileInfo>& colFileInfos,const QString& current_dir,bool bad_chars_in_parent) const ;
|
||||
// check that the file is a valid rscollection file, and not a lol bomb or some shit like this
|
||||
|
Loading…
Reference in New Issue
Block a user