Avoid leaking single shared file path in search results

Single shared files are a bit special and contain the full path in the
  name because they are not shared as part of a directory, epurate the
  path component from matching process and from search result
This commit is contained in:
Gioacchino Mazzurco 2021-07-18 20:14:26 +02:00
parent e1580868dc
commit 9970f9d22f
No known key found for this signature in database
GPG Key ID: A1FBCA3872E87051
2 changed files with 80 additions and 43 deletions

View File

@ -3,7 +3,9 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright 2016 by Mr.Alice <mralice@users.sourceforge.net> *
* Copyright (C) 2016 Mr.Alice <mralice@users.sourceforge.net> *
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.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 *
@ -29,6 +31,7 @@
#include "dir_hierarchy.h"
#include "filelist_io.h"
#include "file_sharing_defaults.h"
#include "util/cxx17retrocompat.h"
#ifdef RS_DEEP_FILES_INDEX
# include "deep_search/filesindex.hpp"
@ -784,27 +787,43 @@ int InternalFileHierarchyStorage::searchTerms(
const std::list<std::string>& terms,
std::list<DirectoryStorage::EntryIndex>& results ) const
{
// most entries are likely to be files, so we could do a linear search over the entries tab.
// instead we go through the table of hashes.
/* most entries are likely to be files, so we could do a linear search over
* the entries tab. Instead we go through the table of hashes.*/
for(std::map<RsFileHash,DirectoryStorage::EntryIndex>::const_iterator it(mFileHashes.begin());it!=mFileHashes.end();++it)
if(mNodes[it->second] != NULL)
{
const std::string &str1 = static_cast<FileEntry*>(mNodes[it->second])->file_name;
for(auto& it : std::as_const(mFileHashes))
{
// node may be null for some hash waiting to be deleted
if(mNodes[it.second])
{
rs_view_ptr<FileEntry> tFileEntry =
static_cast<FileEntry*>(mNodes[it.second]);
for(std::list<std::string>::const_iterator iter(terms.begin()); iter != terms.end(); ++iter)
{
/* always ignore case */
const std::string &str2 = (*iter);
/* Most file will just have file name stored, but single file shared
* without a shared dir will contain full path instead of just the
* name, so purify it to perform the search */
std::string tFilename = tFileEntry->file_name;
if(tFileEntry->file_name.find("/") != std::string::npos)
{
std::string _tParentDir;
RsDirUtil::splitDirFromFile(
tFileEntry->file_name, _tParentDir, tFilename );
}
if(str1.end() != std::search( str1.begin(), str1.end(), str2.begin(), str2.end(), RsRegularExpression::CompareCharIC() ))
{
results.push_back(it->second);
break;
}
}
}
return 0 ;
for(auto& termIt : std::as_const(terms))
{
/* always ignore case */
if(tFilename.end() != std::search(
tFilename.begin(), tFilename.end(),
termIt.begin(), termIt.end(),
RsRegularExpression::CompareCharIC() ))
{
results.push_back(it.second);
break;
}
}
}
}
return 0;
}
bool InternalFileHierarchyStorage::check(std::string& error_string) // checks consistency of storage.

View File

@ -30,7 +30,7 @@
#include "retroshare/rsids.h"
#include "retroshare/rspeers.h"
#include "retroshare/rsinit.h"
#include "util/cxx17retrocompat.h"
#include "rsserver/p3face.h"
#define P3FILELISTS_DEBUG() std::cerr << time(NULL) << " : FILE_LISTS : " << __FUNCTION__ << " : "
@ -1476,7 +1476,9 @@ bool p3FileDatabase::search(
return false;
}
int p3FileDatabase::filterResults(const std::list<void*>& firesults,std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& peer_id) const
int p3FileDatabase::filterResults(
const std::list<void*>& firesults, std::list<DirDetails>& results,
FileSearchFlags flags, const RsPeerId& peer_id ) const
{
results.clear();
@ -1484,29 +1486,33 @@ int p3FileDatabase::filterResults(const std::list<void*>& firesults,std::list<Di
/* translate/filter results */
for(std::list<void*>::const_iterator rit(firesults.begin()); rit != firesults.end(); ++rit)
{
DirDetails cdetails ;
for(void* rit: std::as_const(firesults))
{
DirDetails cdetails;
if(!RequestDirDetails (*rit,cdetails,RS_FILE_HINTS_LOCAL))
{
P3FILELISTS_ERROR() << "(EE) Cannot get dir details for entry " << *rit << std::endl;
continue ;
}
if(!RequestDirDetails(rit, cdetails, RS_FILE_HINTS_LOCAL))
{
RS_ERR("Cannot retrieve dir details for entry: ", rit);
print_stacktrace();
continue ;
}
RS_DBG( "Filtering candidate: ", rit,
", name: ", cdetails.name, ", path: ", cdetails.path,
", flags: ", cdetails.flags, ", peer: ", peer_id );
if(!peer_id.isNull())
{
FileSearchFlags permission_flags =
rsPeers->computePeerPermissionFlags(
peer_id, cdetails.flags, cdetails.parent_groups );
if (cdetails.type == DIR_TYPE_FILE && ( permission_flags & flags ))
{
cdetails.id.clear();
results.push_back(cdetails);
#ifdef DEBUG_P3FILELISTS
P3FILELISTS_DEBUG() << "Filtering candidate " << *rit << ", flags=" << cdetails.flags << ", peer=" << peer_id ;
#endif
if(!peer_id.isNull())
{
FileSearchFlags permission_flags = rsPeers->computePeerPermissionFlags(peer_id,cdetails.flags,cdetails.parent_groups) ;
if (cdetails.type == DIR_TYPE_FILE && ( permission_flags & flags ))
{
cdetails.id.clear() ;
results.push_back(cdetails);
#ifdef DEBUG_P3FILELISTS
std::cerr << ": kept" << std::endl ;
std::cerr << ": kept" << std::endl ;
#endif
}
#ifdef DEBUG_P3FILELISTS
@ -1518,7 +1524,19 @@ int p3FileDatabase::filterResults(const std::list<void*>& firesults,std::list<Di
results.push_back(cdetails);
}
return !results.empty() ;
for(auto& res: results)
{
/* Most file will just have file name stored, but single file shared
* without a shared dir will contain full path instead of just the
* name, so purify it to perform the search */
if(res.name.find("/") != std::string::npos )
{
std::string _tDirPath;
RsDirUtil::splitDirFromFile(res.name, _tDirPath, res.name);
}
}
return !results.empty();
}
bool p3FileDatabase::convertSharedFilePath(const std::string& path,std::string& fullpath)