mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-06-07 14:12:43 -04:00
added resource_api and rs-nogui-webui (requires libmicrohttpd, Html files are not included)
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@8047 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
97831d0667
commit
ad1bc7f3b8
38 changed files with 5547 additions and 2 deletions
240
libresapi/src/api/FileSearchHandler.cpp
Normal file
240
libresapi/src/api/FileSearchHandler.cpp
Normal file
|
@ -0,0 +1,240 @@
|
|||
#include "FileSearchHandler.h"
|
||||
|
||||
#include <retroshare/rsexpr.h>
|
||||
#include <sstream>
|
||||
|
||||
#include "Operators.h"
|
||||
|
||||
namespace resource_api
|
||||
{
|
||||
|
||||
FileSearchHandler::FileSearchHandler(StateTokenServer *sts, RsNotify *notify, RsTurtle *turtle, RsFiles *files):
|
||||
mStateTokenServer(sts), mNotify(notify), mTurtle(turtle), mFiles(files),
|
||||
mMtx("FileSearchHandler")
|
||||
{
|
||||
mNotify->registerNotifyClient(this);
|
||||
addResourceHandler("*", this, &FileSearchHandler::handleWildcard);
|
||||
addResourceHandler("create_search", this, &FileSearchHandler::handleCreateSearch);
|
||||
|
||||
mSearchesStateToken = mStateTokenServer->getNewToken();
|
||||
}
|
||||
|
||||
FileSearchHandler::~FileSearchHandler()
|
||||
{
|
||||
mNotify->unregisterNotifyClient(this);
|
||||
mStateTokenServer->discardToken(mSearchesStateToken);
|
||||
}
|
||||
|
||||
void FileSearchHandler::notifyTurtleSearchResult(uint32_t search_id, const std::list<TurtleFileInfo>& files)
|
||||
{
|
||||
RsStackMutex stackMtx(mMtx); // ********** STACK LOCKED MTX **********
|
||||
std::map<uint32_t, Search>::iterator mit = mSearches.find(search_id);
|
||||
if(mit == mSearches.end())
|
||||
return;
|
||||
|
||||
Search& search = mit->second;
|
||||
// set to a limit of 100 for now, can have more when we have pagination
|
||||
std::list<TurtleFileInfo>::const_iterator lit = files.begin();
|
||||
bool changed = false;
|
||||
while(search.mResults.size() < 100 && lit != files.end())
|
||||
{
|
||||
if(search.mHashes.find(lit->hash) == search.mHashes.end())
|
||||
{
|
||||
changed = true;
|
||||
FileDetail det ;
|
||||
det.rank = 0 ;
|
||||
det.age = 0 ;
|
||||
det.name = (*lit).name;
|
||||
det.hash = (*lit).hash;
|
||||
det.size = (*lit).size;
|
||||
det.id.clear();
|
||||
search.mResults.push_back(det);
|
||||
search.mHashes.insert(lit->hash);
|
||||
}
|
||||
lit++;
|
||||
}
|
||||
if(changed)
|
||||
{
|
||||
mStateTokenServer->discardToken(search.mStateToken);
|
||||
search.mStateToken = mStateTokenServer->getNewToken();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: delete searches
|
||||
void FileSearchHandler::handleWildcard(Request &req, Response &resp)
|
||||
{
|
||||
if(!req.mPath.empty())
|
||||
{
|
||||
std::string str = req.mPath.top();
|
||||
req.mPath.pop();
|
||||
|
||||
if(str.size() != 8)
|
||||
{
|
||||
resp.setFail("Error: id has wrong size, should be 8 characters");
|
||||
return;
|
||||
}
|
||||
uint32_t id = 0;
|
||||
// TODO fix this
|
||||
for(uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
id += (uint32_t(str[i]-'A')) << (i*4);
|
||||
}
|
||||
|
||||
{
|
||||
RsStackMutex stackMtx(mMtx); // ********** STACK LOCKED MTX **********
|
||||
std::map<uint32_t, Search>::iterator mit = mSearches.find(id);
|
||||
if(mit == mSearches.end())
|
||||
{
|
||||
resp.setFail("Error: search id invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
Search& search = mit->second;
|
||||
resp.mStateToken = search.mStateToken;
|
||||
resp.mDataStream.getStreamToMember();
|
||||
for(std::list<FileDetail>::iterator lit = search.mResults.begin(); lit != search.mResults.end(); ++lit)
|
||||
{
|
||||
FileDetail& fd = *lit;
|
||||
double size = fd.size;
|
||||
resp.mDataStream.getStreamToMember()
|
||||
<< makeKeyValueReference("id", fd.hash)
|
||||
<< makeKeyValueReference("name", fd.name)
|
||||
<< makeKeyValueReference("hash", fd.hash)
|
||||
<< makeKeyValueReference("size", size)
|
||||
<< makeKeyValueReference("rank", fd.rank);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// list searches
|
||||
RsStackMutex stackMtx(mMtx); // ********** STACK LOCKED MTX **********
|
||||
resp.mDataStream.getStreamToMember();
|
||||
for(std::map<uint32_t, Search>::iterator mit = mSearches.begin(); mit != mSearches.end(); ++mit)
|
||||
{
|
||||
uint32_t id = mit->first;
|
||||
std::string idstr;
|
||||
// how many times do i have to write int to string conversation?
|
||||
// a library should do this
|
||||
for(uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
char c = ((id>>(i*4))&0xF)+'A';
|
||||
idstr += c;
|
||||
}
|
||||
resp.mDataStream.getStreamToMember()
|
||||
<< makeKeyValueReference("id", idstr)
|
||||
<< makeKeyValueReference("search_string", mit->second.mSearchString);
|
||||
}
|
||||
resp.mStateToken = mSearchesStateToken;
|
||||
resp.setOk();
|
||||
}
|
||||
}
|
||||
|
||||
static bool dirDetailToFileDetail(const DirDetails& dir, FileDetail& fd)
|
||||
{
|
||||
if (dir.type == DIR_TYPE_FILE)
|
||||
{
|
||||
fd.id = dir.id;
|
||||
fd.name = dir.name;
|
||||
fd.hash = dir.hash;
|
||||
fd.path = dir.path;
|
||||
fd.size = dir.count;
|
||||
fd.age = dir.age;
|
||||
fd.rank = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// see retroshare-gui/src/gui/Searchdialog.cpp
|
||||
void FileSearchHandler::handleCreateSearch(Request &req, Response &resp)
|
||||
{
|
||||
bool distant = false;// distant involves sending data, so have it off by default for privacy
|
||||
bool local = true;
|
||||
bool remote = true;
|
||||
std::string search_string;
|
||||
req.mStream << makeKeyValueReference("distant", distant)
|
||||
<< makeKeyValueReference("local", local)
|
||||
<< makeKeyValueReference("remote", remote)
|
||||
<< makeKeyValueReference("search_string", search_string);
|
||||
|
||||
std::istringstream iss(search_string);
|
||||
std::list<std::string> words;
|
||||
std::string s;
|
||||
while (std::getline(iss, s, ' ')) {
|
||||
std::cout << s << std::endl;
|
||||
words.push_back(s);
|
||||
}
|
||||
|
||||
if(words.empty())
|
||||
{
|
||||
resp.setFail("Error: no search string given");
|
||||
return;
|
||||
}
|
||||
|
||||
NameExpression exprs(ContainsAllStrings,words,true) ;
|
||||
LinearizedExpression lin_exp ;
|
||||
exprs.linearize(lin_exp) ;
|
||||
|
||||
uint32_t search_id = RSRandom::random_u32();
|
||||
if(distant)
|
||||
{
|
||||
// i have no idea what the reasons for two different search modes are
|
||||
// rs-gui does it, so do we
|
||||
if(words.size() == 1)
|
||||
search_id = mTurtle->turtleSearch(words.front());
|
||||
else
|
||||
search_id = mTurtle->turtleSearch(lin_exp);
|
||||
}
|
||||
|
||||
std::list<FileDetail> results;
|
||||
if(local)
|
||||
{
|
||||
std::list<DirDetails> local_results;
|
||||
rsFiles->SearchBoolExp(&exprs, local_results, RS_FILE_HINTS_LOCAL);
|
||||
|
||||
for(std::list<DirDetails>::iterator lit = local_results.begin(); lit != local_results.end(); ++lit)
|
||||
{
|
||||
FileDetail fd;
|
||||
if(dirDetailToFileDetail(*lit, fd))
|
||||
results.push_back(fd);
|
||||
}
|
||||
}
|
||||
if(remote)
|
||||
{
|
||||
std::list<DirDetails> remote_results;
|
||||
rsFiles->SearchBoolExp(&exprs, remote_results, RS_FILE_HINTS_REMOTE);
|
||||
for(std::list<DirDetails>::iterator lit = remote_results.begin(); lit != remote_results.end(); ++lit)
|
||||
{
|
||||
FileDetail fd;
|
||||
if(dirDetailToFileDetail(*lit, fd))
|
||||
results.push_back(fd);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
RsStackMutex stackMtx(mMtx); // ********** STACK LOCKED MTX **********
|
||||
|
||||
Search& search = mSearches[search_id];
|
||||
search.mStateToken = mStateTokenServer->getNewToken();
|
||||
search.mSearchString = search_string;
|
||||
search.mResults.swap(results);
|
||||
|
||||
mStateTokenServer->discardToken(mSearchesStateToken);
|
||||
mSearchesStateToken = mStateTokenServer->getNewToken();
|
||||
}
|
||||
|
||||
std::string idstr;
|
||||
// how many times do i have to write int to string conversation?
|
||||
// a library should do this
|
||||
for(uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
char c = ((search_id>>(i*4))&0xF)+'A';
|
||||
idstr += c;
|
||||
}
|
||||
resp.mDataStream << makeKeyValueReference("search_id", idstr);
|
||||
resp.setOk();
|
||||
}
|
||||
|
||||
} // namespace resource_api
|
Loading…
Add table
Add a link
Reference in a new issue