Initial work on RsFiles links support in libretroshare

This commit is contained in:
Gioacchino Mazzurco 2020-03-11 23:11:59 +01:00
parent b6c5e2f188
commit 55d466f79b
No known key found for this signature in database
GPG Key ID: A1FBCA3872E87051
16 changed files with 438 additions and 179 deletions

View File

@ -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 ;
RS_SERIAL_PROCESS(name);
RS_SERIAL_PROCESS(subdirs);
RS_SERIAL_PROCESS(subfiles);
}
void RsFileTree::FileData::serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
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;
}
FileTree *FileTree::create(const std::string& radix64_string)
std::unique_ptr<RsFileTree> RsFileTree::fromRadix64(
const std::string& radix64_string )
{
FileTreeImpl *ft = new FileTreeImpl ;
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) ;
@ -74,7 +123,7 @@ void FileTreeImpl::recurs_buildFileTree(FileTreeImpl& ft,uint32_t index,const Di
{
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) ;
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;
}
}

View File

@ -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 ;
};

View File

@ -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;
}

View File

@ -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.
***/

View File

@ -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 \

View File

@ -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 {
/// @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;
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;
};

View File

@ -210,8 +210,8 @@ 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.
//
/// @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.

View File

@ -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;
/**

View File

@ -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) ;

View File

@ -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;

View File

@ -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);

View File

@ -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
{

View File

@ -2225,8 +2225,7 @@ void TransfersDialog::pasteLink()
for(QList<RetroShareLink>::const_iterator it(links.begin());it!=links.end();++it)
{
FileTree *ft = FileTree::create((*it).radix().toStdString()) ;
auto ft = RsFileTree::fromRadix64((*it).radix().toStdString());
col.merge_in(*ft);
}
links.clear();

View File

@ -1708,13 +1708,11 @@ static void processList(const QStringList &list, const QString &textSingular, co
case TYPE_FILE_TREE:
{
FileTree *ft = FileTree::create(link.radix().toStdString()) ;
auto ft = RsFileTree::fromRadix64(
link.radix().toStdString() );
RsCollection(*ft).downloadFiles();
delete ft;
}
break;
}
case TYPE_CHAT_ROOM:
{

View File

@ -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())) ;

View File

@ -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