Пример #1
0
/**
  * Send the results from a query to the asker
  * The query's encoding should be UTF-8
  */
void Museek::SearchManager::sendSearchResults(const std::string & username, const std::string & query, uint token) {
	if(! museekd()->isBanned(username) && (username != museekd()->server()->username())) {
        SharesDatabase* db;

        if (museekd()->isBuddied(username))
            db = museekd()->buddyshares();
        else
            db = museekd()->shares();

        Folder results;
        db->search(query, results);

        if (!results.empty()) {
            m_PendingResults[username][token] = results;
            museekd()->peers()->peerSocket(username, false);
        }
	}
}
Пример #2
0
/* this is the best I can do I think... */
void Museek::SharesDatabase::search(const string& _query, Folder& result) {
 	NNLOG("museekd.shares.debug", "sharesdatabase search %s", _query.c_str());

	string query = _query;

	size_t results = 0;

	string word;

	if(query.empty())
		return;

	/* add a space to make sure we also get the last word */
	query += (wchar_t)' ';

	vector<Folder* > q_in; // foobar
	StringList q_out; // -foobar
	StringList q_part; // *foobar "foo bar"
	bool quoted = false, was_quoted = false;

	/* breaks up the query into in-groups, out-files and terms */
	string::iterator sit = query.begin();
	for(; sit != query.end(); ++sit) {
		if(*sit == '"') {
			quoted = ! quoted;
			was_quoted = true;
			continue;
		}

		wchar_t c = mutate(*sit, quoted ? false : word.empty());
		if(! quoted && c == ' ') {
			wchar_t firstC = word[0];
			if(was_quoted || firstC == '*') {
			    if (firstC == '*')
                    word = word.substr(1);
				q_part.push_back(word);
			}
			else if(firstC == '-') {
			    if (word.size() > 0)
                    q_out.push_back(mMuseekd->codeset()->toNet(string(word.data() + 1, word.size() - 1)));
			}
			else {
				/* find files that match this word */
				Folder* t = &mCharMap[word[0]][word];
				if(! t->empty())
					q_in.push_back(t);
				else
					return;
			}
			was_quoted = false;
			word = string();
			continue;
		}
		word += c;
	}

	if(q_in.empty() && q_part.empty())
		return;

    else if (!q_in.empty()) {
        Folder* base = q_in[0];
        vector<Folder* >::const_iterator first = q_in.begin()++;
        Folder::const_iterator it = base->begin();
        for(; it != base->end(); ++it) {
            // Did we already found this result?
            if(result.find((*it).first) != result.end())
                continue;

            // Don't add results that contains forbidden words
            if(! q_out.empty()) {
                string lowr = tolower((*it).first);
                StringList::const_iterator oit = q_out.begin();
                for(; oit != q_out.end(); ++oit)
                    if(lowr.find(*oit) != string::npos)
                        break;
                if(oit != q_out.end())
                    continue;
            }

            // If we arrive here, we can add the file to the results if it matches every keyword
            vector<Folder* >::const_iterator ref = first;
            for(; ref != q_in.end(); ++ref)
                if((*ref)->find((*it).first) == (*ref)->end())
                    break;

            if(ref == q_in.end()) {
                // Ok, it matches every keyword, but does it match every phrase?
                StringList::const_iterator partit = q_part.begin();
                for(; partit != q_part.end(); ++partit)
                    if (tolower((*it).first).find(tolower(*partit)) == std::string::npos)
                        break;

                if(partit == q_part.end()) {
                    result[(*it).first] = (*it).second;
                    ++results;
                }
            }

            // Don't send more than 500 results
            if(results >= 500)
                return;
        }
    }
    else {
        // We're only searching phrases (*foobar "foo bar"), search in flat list
        Folder::iterator fit = mFlat.begin();
        StringList::const_iterator wit;
        for(; fit != mFlat.end(); ++fit) {
            string entry = tolower(mMuseekd->codeset()->fromNet((*fit).first));
            bool notFound = false;

            for (wit = q_part.begin(); wit != q_part.end(); wit++) {
                size_t posFound = entry.find(tolower(*wit));
                if (posFound == std::string::npos) {
                    notFound = true;
                    break;
                }
            }

            if (!notFound) {
                result[(*fit).first] = (*fit).second;
                ++results;
            }

            // Don't send more than 500 results
            if(results >= 500)
                return;
        }
    }
}