SearchResultList ShareManager::search(SearchQuery&& query, size_t maxResults) noexcept { SearchResultList results; Lock l(cs); if(query.root != NULL) { auto i = tthIndex.find(*(query.root)); if(i != tthIndex.end()) { results.push_back(new SearchResult(SearchResult::TYPE_FILE, i->second->getSize(), i->second->getParent()->getFullName() + i->second->getName(), i->second->tth)); addHits(1); } return results; } for(auto& i: query.includeInit) { if(!bloom.match(i.getPattern())) return results; } for(auto& dir: directories) { dir.second->search(results, query, maxResults); if(results.size() >= maxResults) { return results; } } return results; }
api_return SearchResultInfo::download(const string& aTargetDirectory, const string& aTargetName, TargetUtil::TargetType aTargetType, QueueItemBase::Priority aPrio) { bool fileDownload = sr->getType() == SearchResult::TYPE_FILE; auto download = [&](const SearchResultPtr& aSR) { if (fileDownload) { QueueManager::getInstance()->createFileBundle(aTargetDirectory + aTargetName, sr->getSize(), sr->getTTH(), sr->getUser(), sr->getDate(), 0, aPrio); } else { DirectoryListingManager::getInstance()->addDirectoryDownload(aSR->getFilePath(), aTargetName, aSR->getUser(), aTargetDirectory, aTargetType, false, aPrio, false, 0, false, false); } }; if (hits >= 1) { //perform also for the children SearchResultList results = { sr }; for (auto si : children) results.push_back(si->sr); SearchResult::pickResults(results, SETTING(MAX_AUTO_MATCH_SOURCES)); boost::for_each(results, download); } else { //perform for the parent download(sr); } return websocketpp::http::status_code::ok; }
/** * Alright, the main point here is that when searching, a search string is most often found in * the filename, not directory name, so we want to make that case faster. Also, we want to * avoid changing StringLists unless we absolutely have to --> this should only be done if a string * has been matched in the directory name. This new stringlist should also be used in all descendants, * but not the parents... */ void ShareManager::Directory::search(SearchResultList& results, SearchQuery& query, size_t maxResults) const noexcept { if(query.isExcluded(name)) return; // Find any matches in the directory name and removed matched terms from the query. StringSearch::List newTerms; for(auto& term: query.include) { if(term.match(name)) { if(!newTerms.empty()) { newTerms = query.include; } newTerms.erase(remove(newTerms.begin(), newTerms.end(), term), newTerms.end()); } } // auto const old = query.include; if(!newTerms.empty()) { query.include = newTerms; } if(query.include.empty() && query.ext.empty() && query.gt == 0) { // We satisfied all the search words! Add the directory... /// @todo send the directory hash when we have one results.push_back(new SearchResult(SearchResult::TYPE_DIRECTORY, getSize(), getFullName(), TTHValue(string(39, 'A')))); ShareManager::getInstance()->addHits(1); } if(!query.isDirectory) { for(auto& i: files) { if(!i.tth) { continue; } // check the size if(!(i.getSize() >= query.gt)) { continue; } else if(!(i.getSize() <= query.lt)) { continue; } if(query.isExcluded(i.getName())) continue; // check if the name matches auto j = query.include.begin(); for(; j != query.include.end() && j->match(i.getName()); ++j) ; // Empty if(j != query.include.end()) continue; // check extensions if(!query.hasExt(i.getName())) continue; results.push_back(new SearchResult(SearchResult::TYPE_FILE, i.getSize(), getFullName() + i.getName(), (i.tth))); ShareManager::getInstance()->addHits(1); if(results.size() >= maxResults) { return; } } } for(auto& dir: directories) { dir.second->search(results, query, maxResults); if(results.size() >= maxResults) { return; } } }
bool Search::handleIqID( Stanza *stanza, int context ) { TrackMap::iterator it = m_track.find( stanza->id() ); if( it != m_track.end() ) { switch( stanza->subtype() ) { case StanzaIqResult: switch( context ) { case FetchSearchFields: { Tag *q = stanza->findChild( "query" ); if( q && q->hasAttribute( "xmlns", XMLNS_SEARCH ) ) { Tag *x = q->findChild( "x", "xmlns", XMLNS_X_DATA ); if( x ) { DataForm *df = new DataForm( x ); (*it).second->handleSearchFields( stanza->from(), df ); } else { int fields = 0; std::string instructions; if( q->hasChild( "first" ) ) fields |= SearchFieldFirst; if( q->hasChild( "last" ) ) fields |= SearchFieldLast; if( q->hasChild( "nick" ) ) fields |= SearchFieldNick; if( q->hasChild( "email" ) ) fields |= SearchFieldEmail; if( q->hasChild( "instructions" ) ) instructions = q->findChild( "instructions" )->cdata(); (*it).second->handleSearchFields( stanza->from(), fields, instructions ); } } break; } case DoSearch: { Tag *q = stanza->findChild( "query" ); if( q && q->hasAttribute( "xmlns", XMLNS_SEARCH ) ) { Tag *x = q->findChild( "x", "xmlns", XMLNS_X_DATA ); if( x ) { DataForm *df = new DataForm( x ); (*it).second->handleSearchResult( stanza->from(), df ); } else { SearchResultList e; SearchFieldStruct s; const Tag::TagList &l = q->children(); Tag::TagList::const_iterator itl = l.begin(); for( ; itl != l.end(); ++itl ) { if( (*itl)->name() == "item" ) { s.jid.setJID( (*itl)->findAttribute( "jid" ) ); Tag *t = 0; if( ( t = (*itl)->findChild( "first" ) ) != 0 ) s.first = t->cdata(); if( ( t = (*itl)->findChild( "last" ) ) != 0 ) s.last = t->cdata(); if( ( t = (*itl)->findChild( "nick" ) ) != 0 ) s.nick = t->cdata(); if( ( t = (*itl)->findChild( "email" ) ) != 0 ) s.email = t->cdata(); e.push_back( s ); } } (*it).second->handleSearchResult( stanza->from(), e ); } } break; } } break; case StanzaIqError: (*it).second->handleSearchError( stanza->from(), stanza ); break; default: break; } m_track.erase( it ); } return false; }