Beispiel #1
0
SearchQuery::SearchQuery(const string& nmdcString, Search::SizeModes aSizeMode, int64_t size, Search::TypeModes aFileType, size_t aMaxResults) noexcept : maxResults(aMaxResults) {
	if (aFileType == Search::TYPE_TTH && nmdcString.compare(0, 4, "TTH:") == 0) {
		root = TTHValue(nmdcString.substr(4));

	} else {
		StringTokenizer<string> tok(Text::toLower(nmdcString), '$');
		for (auto& term : tok.getTokens()) {
			if (!term.empty()) {
				include.addString(term);
			}
		}

		if (aSizeMode == Search::SIZE_ATLEAST) {
			gt = size;
		} else if (aSizeMode == Search::SIZE_ATMOST) {
			lt = size;
		}

		switch (aFileType) {
		case Search::TYPE_AUDIO: ext = AdcHub::parseSearchExts(1 << 0); break;
		case Search::TYPE_COMPRESSED: ext = AdcHub::parseSearchExts(1 << 1); break;
		case Search::TYPE_DOCUMENT: ext = AdcHub::parseSearchExts(1 << 2); break;
		case Search::TYPE_EXECUTABLE: ext = AdcHub::parseSearchExts(1 << 3); break;
		case Search::TYPE_PICTURE: ext = AdcHub::parseSearchExts(1 << 4); break;
		case Search::TYPE_VIDEO: ext = AdcHub::parseSearchExts(1 << 5); break;
		case Search::TYPE_DIRECTORY: itemType = SearchQuery::TYPE_DIRECTORY; break;
		default: break;
		}
	}

	prepare();
}
Beispiel #2
0
	/*
	 * Loads existing indexes from disk
	 */
	void IndexManager::loadIndexes(SimpleXML& xml)
	{
		xml.resetCurrentChild();
		if(xml.findChild("Files"))
		{
			xml.stepIn();
			while(xml.findChild("File"))
			{
				const TTHValue tth = TTHValue(xml.getChildAttrib("TTH"));
				SourceList sources;

				xml.stepIn();
				while(xml.findChild("Source"))
				{
					Source source;
					source.setCID(CID(xml.getChildAttrib("CID")));
					source.setIp(xml.getChildAttrib("I4"));
					source.setUdpPort(static_cast<uint16_t>(xml.getIntChildAttrib("U4")));
					source.setSize(xml.getLongLongChildAttrib("SI"));
					source.setExpires(xml.getLongLongChildAttrib("EX"));
					source.setPartial(false);

					sources.push_back(source);
				}

				tthList.insert(std::make_pair(tth, sources));
				xml.stepOut();
			}
			xml.stepOut();
		}
	}
	TTHValue Deserializer::parseTTH(const string& aTTH) {
		if (!Encoder::isBase32(aTTH.c_str())) {
			throw std::invalid_argument("Invalid TTH");
		}

		return TTHValue(aTTH);
	}
Beispiel #4
0
LRESULT TempShareDlg::onRemove(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {

	TCHAR buf[MAX_PATH];
	LVITEM item;
	memzero(&item, sizeof(item));
	item.mask = LVIF_TEXT;
	item.cchTextMax = sizeof(buf);
	item.pszText = buf;

	int i = -1;
	while ((i = ctrlFiles.GetNextItem(-1, LVNI_SELECTED)) != -1) {
		item.iItem = i;

		item.iSubItem = 2;
		ctrlFiles.GetItem(&item);
		TTHValue tth = TTHValue(Text::fromT(buf));

		item.iSubItem = 3;
		ctrlFiles.GetItem(&item);
		string key = Text::fromT(buf);

		ShareManager::getInstance()->removeTempShare(key, tth);
		ctrlFiles.DeleteItem(i);
	}
	return 0;
}
Beispiel #5
0
	TTHValue Deserializer::deserializeTTH(const json& aJson) {
		auto tthStr = JsonUtil::getField<string>("tth", aJson, false);
		if (!Encoder::isBase32(tthStr.c_str())) {
			throw std::invalid_argument("Invalid TTH");
		}

		return TTHValue(tthStr);
	}
Beispiel #6
0
void SearchManager::respond(const AdcCommand& adc, const CID& from,  bool isUdpActive, const string& hubIpPort) {
    // Filter own searches
    if(from == ClientManager::getInstance()->getMe()->getCID())
        return;

    UserPtr p = ClientManager::getInstance()->findUser(from);
    if(!p)
        return;

    SearchResultList results;
    ShareManager::getInstance()->search(results, adc.getParameters(), isUdpActive ? 10 : 5);

    string token;

    adc.getParam("TO", 0, token);

    // TODO: don't send replies to passive users
    if(results.empty()) {
        string tth;
        if(!adc.getParam("TR", 0, tth))
                return;

        PartsInfo partialInfo;
        if(!QueueManager::getInstance()->handlePartialSearch(TTHValue(tth), partialInfo)) {
                // if not found, try to find in finished list
                if(!FinishedManager::getInstance()->handlePartialRequest(TTHValue(tth), partialInfo)) {
                        return;
                }
        }

        AdcCommand cmd = toPSR(true, Util::emptyString, hubIpPort, tth, partialInfo);
        ClientManager::getInstance()->send(cmd, from);
        return;
    }

    for(SearchResultList::const_iterator i = results.begin(); i != results.end(); ++i) {
        AdcCommand cmd = (*i)->toRES(AdcCommand::TYPE_UDP);
        if(!token.empty())
            cmd.addParam("TO", token);
        ClientManager::getInstance()->send(cmd, from);
    }
}
	virtual size_t write(const void* xbuf, size_t len) throw(Exception) {
		size_t pos = 0;
		u_int8_t* b = (u_int8_t*)xbuf;
		while(pos < len) {
			size_t left = len - pos;
			if(bufPos == 0 && left >= TigerTree::HASH_SIZE) {
				tree.getLeaves().push_back(TTHValue(b + pos));
				pos += TigerTree::HASH_SIZE;
			} else {
				size_t bytes = min(TigerTree::HASH_SIZE - bufPos, left);
				memcpy(buf + bufPos, b + pos, bytes);
				bufPos += bytes;
				pos += bytes;
				if(bufPos == TigerTree::HASH_SIZE) {
					tree.getLeaves().push_back(TTHValue(buf));
					bufPos = 0;
				}
			}
		}
		return len;
	}
void SearchManager::onRES(const AdcCommand& cmd, const UserPtr& from, const string& remoteIp) {
	int freeSlots = -1;
	int64_t size = -1;
	string file;
	string tth;
	string token;

	for(auto& str: cmd.getParameters()) {
		if(str.compare(0, 2, "FN") == 0) {
			file = Util::toNmdcFile(str.substr(2));
		} else if(str.compare(0, 2, "SL") == 0) {
			freeSlots = Util::toInt(str.substr(2));
		} else if(str.compare(0, 2, "SI") == 0) {
			size = Util::toInt64(str.substr(2));
		} else if(str.compare(0, 2, "TR") == 0) {
			tth = str.substr(2);
		} else if(str.compare(0, 2, "TO") == 0) {
			token = str.substr(2);
		}
	}

	if(file.empty() || freeSlots == -1 || size == -1) { return; }

	auto type = (*(file.end() - 1) == '\\' ? SearchResult::TYPE_DIRECTORY : SearchResult::TYPE_FILE);
	if(type == SearchResult::TYPE_FILE && tth.empty()) { return; }

	string hubUrl;

	// token format: [per-hub unique id] "/" [per-search actual token] (see AdcHub::search)
	auto slash = token.find('/');
	if(slash == string::npos) { return; }
	{
		auto uniqueId = Util::toUInt32(token.substr(0, slash));
		auto lock = ClientManager::getInstance()->lock();
		auto& clients = ClientManager::getInstance()->getClients();
		auto i = boost::find_if(clients, [uniqueId](const Client* client) { return client->getUniqueId() == uniqueId; });
		if(i == clients.end()) { return; }
		hubUrl = (*i)->getHubUrl();
	}
	token.erase(0, slash + 1);

	StringList names = ClientManager::getInstance()->getHubNames(from->getCID());
	string hubName = names.empty() ? _("Offline") : Util::toString(names);

	/// @todo Something about the slots
	fire(SearchManagerListener::SR(), SearchResultPtr(new SearchResult(HintedUser(from, hubUrl),
		type, 0, freeSlots, size, file, hubName, remoteIp, TTHValue(tth), token)));
}
Beispiel #9
0
const ShareManager::Directory::File& ShareManager::findFile(const string& virtualFile) const {
	if(virtualFile.compare(0, 4, "TTH/") == 0) {
		auto i = tthIndex.find(TTHValue(virtualFile.substr(4)));
		if(i == tthIndex.end()) {
			throw ShareException(UserConnection::FILE_NOT_AVAILABLE);
		}
		return *i->second;
	}

	auto v = splitVirtual(virtualFile);
	auto it = find_if(v.first->files.begin(), v.first->files.end(),
		Directory::File::StringComp(v.second));
	if(it == v.first->files.end())
		throw ShareException(UserConnection::FILE_NOT_AVAILABLE);
	return *it;
}
Beispiel #10
0
MemoryInputStream* ShareManager::getTree(const string& virtualFile) const {
	TigerTree tree;
	if(virtualFile.compare(0, 4, "TTH/") == 0) {
		if(!HashManager::getInstance()->getTree(TTHValue(virtualFile.substr(4)), tree))
			return nullptr;
	} else {
		try {
			TTHValue tth = getTTH(virtualFile);
			//if(!tth) { return nullptr; }
			HashManager::getInstance()->getTree(tth, tree);
		} catch(const Exception&) {
			return nullptr;
		}
	}

	ByteVector buf = tree.getLeafData();
	return new MemoryInputStream(&buf[0], buf.size());
}
AdcSearch* AdcSearch::getSearch(const string& aSearchString, const string& aExcluded, int64_t aSize, int aTypeMode, int aSizeMode, const StringList& aExtList, MatchType aMatchType, bool returnParents) {
	AdcSearch* s = nullptr;

	if(aTypeMode == SearchManager::TYPE_TTH) {
		s = new AdcSearch(TTHValue(aSearchString));
	} else {
		s = new AdcSearch(aSearchString, aExcluded, aExtList, aMatchType);
		if(aSizeMode == SearchManager::SIZE_ATLEAST) {
			s->gt = aSize;
		} else if(aSizeMode == SearchManager::SIZE_ATMOST) {
			s->lt = aSize;
		}

		s->itemType = (aTypeMode == SearchManager::TYPE_DIRECTORY) ? AdcSearch::TYPE_DIRECTORY : (aTypeMode == SearchManager::TYPE_FILE) ? AdcSearch::TYPE_FILE : AdcSearch::TYPE_ANY;
		s->addParents = returnParents;
	}

	return s;
}
Beispiel #12
0
SearchQuery* SearchQuery::getSearch(const SearchPtr& aSearch) noexcept {
	SearchQuery* s = nullptr;

	if(aSearch->fileType == Search::TYPE_TTH) {
		s = new SearchQuery(TTHValue(aSearch->query));
	} else {
		s = new SearchQuery(aSearch->query, aSearch->excluded, aSearch->exts, aSearch->matchType);
		if(aSearch->sizeType == Search::SIZE_ATLEAST) {
			s->gt = aSearch->size;
		} else if(aSearch->sizeType == Search::SIZE_ATMOST) {
			s->lt = aSearch->size;
		}

		s->itemType = (aSearch->fileType == Search::TYPE_DIRECTORY) ? SearchQuery::TYPE_DIRECTORY : (aSearch->fileType == Search::TYPE_FILE) ? SearchQuery::TYPE_FILE : SearchQuery::TYPE_ANY;
	}

	s->addParents = aSearch->returnParents;
	s->maxResults = aSearch->maxResults;
	return s;
}
Beispiel #13
0
SearchQuery::SearchQuery(const StringList& params, size_t aMaxResults) noexcept : maxResults(aMaxResults) {
	for(const auto& p: params) {
		if(p.length() <= 2)
			continue;

		uint16_t cmd = toCode(p[0], p[1]);
		if(toCode('T', 'R') == cmd) {
			root = TTHValue(p.substr(2));
			return;
		} else if(toCode('A', 'N') == cmd) {
			include.addString(p.substr(2));
		} else if(toCode('N', 'O') == cmd) {
			exclude.addString(p.substr(2));
		} else if(toCode('E', 'X') == cmd) {
			ext.push_back(Text::toLower(p.substr(2)));
		} else if(toCode('G', 'R') == cmd) {
			auto exts = AdcHub::parseSearchExts(Util::toInt(p.substr(2)));
			ext.insert(ext.begin(), exts.begin(), exts.end());
		} else if(toCode('R', 'X') == cmd) {
			noExt.push_back(Text::toLower(p.substr(2)));
		} else if(toCode('G', 'E') == cmd) {
			gt = Util::toInt64(p.substr(2));
		} else if(toCode('L', 'E') == cmd) {
			lt = Util::toInt64(p.substr(2));
		} else if(toCode('E', 'Q') == cmd) {
			lt = gt = Util::toInt64(p.substr(2));
		} else if(toCode('T', 'Y') == cmd) {
			itemType = static_cast<ItemType>(Util::toInt(p.substr(2)));
		} else if(toCode('M', 'T') == cmd) {
			matchType = static_cast<Search::MatchType>(Util::toInt(p.substr(2)));
		} else if(toCode('O', 'T') == cmd) {
			maxDate = Util::toInt64(p.substr(2));
		} else if(toCode('N', 'T') == cmd) {
			minDate = Util::toInt64(p.substr(2));
		} else if(toCode('P', 'P') == cmd) {
			addParents = (p[2] == '1');
		}
	}

	prepare();
}
    /*
     * Processes incoming request to publish file
     */
    void IndexManager::processPublishSourceRequest(const Node::Ptr& node, const AdcCommand& cmd)
    {
        string tth;
        if(!cmd.getParam("TR", 1, tth))
            return; // nothing to identify a file?

        string size;
        if(!cmd.getParam("SI", 1, size))
            return; // no file size?

        string partial;
        cmd.getParam("PF", 1, partial);

        addSource(TTHValue(tth), node, Util::toInt64(size), partial == "1");

        // send response
        AdcCommand res(AdcCommand::SEV_SUCCESS, AdcCommand::SUCCESS, "File published", AdcCommand::TYPE_UDP);
        res.addParam("FC", "PUB");
        res.addParam("TR", tth);
        DHT::getInstance()->send(res, node->getIdentity().getIp(), node->getIdentity().getUdpPort(), node->getUser()->getCID(), node->getUdpKey());
    }
Beispiel #15
0
void SearchManager::onRES(const AdcCommand& cmd, const UserPtr& from, const string& remoteIp) {
    int freeSlots = -1;
    int64_t size = -1;
    string file;
    string tth;
    string token;

    for(StringIterC i = cmd.getParameters().begin(); i != cmd.getParameters().end(); ++i) {
        const string& str = *i;
        if(str.compare(0, 2, "FN") == 0) {
            file = Util::toNmdcFile(str.substr(2));
        } else if(str.compare(0, 2, "SL") == 0) {
            freeSlots = Util::toInt(str.substr(2));
        } else if(str.compare(0, 2, "SI") == 0) {
            size = Util::toInt64(str.substr(2));
        } else if(str.compare(0, 2, "TR") == 0) {
            tth = str.substr(2);
        } else if(str.compare(0, 2, "TO") == 0) {
            token = str.substr(2);
        }
    }

    if(!file.empty() && freeSlots != -1 && size != -1) {

        /// @todo get the hub this was sent from, to be passed as a hint? (eg by using the token?)
        StringList names = ClientManager::getInstance()->getHubNames(from->getCID(), Util::emptyString);
        string hubName = names.empty() ? _("Offline") : Util::toString(names);
        StringList hubs = ClientManager::getInstance()->getHubs(from->getCID(), Util::emptyString);
        string hub = hubs.empty() ? _("Offline") : Util::toString(hubs);

        SearchResult::Types type = (file[file.length() - 1] == '\\' ? SearchResult::TYPE_DIRECTORY : SearchResult::TYPE_FILE);
        if(type == SearchResult::TYPE_FILE && tth.empty())
            return;
        /// @todo Something about the slots
        SearchResultPtr sr(new SearchResult(from, type, 0, freeSlots, size,
            file, hubName, hub, remoteIp, TTHValue(tth), token));
        fire(SearchManagerListener::SR(), sr);
    }
}
Beispiel #16
0
	/*
	 * Processes incoming request to publish file
	 */
	void IndexManager::processPublishSourceRequest(const string& ip, uint16_t port, const UDPKey& udpKey, const AdcCommand& cmd)
	{
	const CID cid = CID(cmd.getParam(0));

		string tth;
		if(!cmd.getParam("TR", 1, tth))
			return;	// nothing to identify a file?

		string size;
		if(!cmd.getParam("SI", 1, size))
			return;	// no file size?

		string partial;
		cmd.getParam("PF", 1, partial);

		addSource(TTHValue(tth), cid, ip, port, Util::toInt64(size), partial == "1");

		// send response
		AdcCommand res(AdcCommand::SEV_SUCCESS, AdcCommand::SUCCESS, "File published", AdcCommand::TYPE_UDP);
		res.addParam("FC", "PUB");
		res.addParam("TR", tth);
		DHT::getInstance()->send(res, ip, port, cid, udpKey);
	}
Beispiel #17
0
void ListLoader::startTag(const string& name, StringPairList& attribs, bool simple)
{
#ifdef _DEBUG
	static size_t g_max_attribs_size = 0;
	if (g_max_attribs_size != attribs.size())
	{
		g_max_attribs_size = attribs.size();
		// dcdebug("ListLoader::startTag g_max_attribs_size = %d , attribs.capacity() = %d\n", g_max_attribs_size, attribs.capacity());
	}
#endif
	if (ClientManager::isBeforeShutdown())
	{
		throw AbortException("ListLoader::startTag - ClientManager::isBeforeShutdown()");
	}
	if (m_list->getAbort())
	{
		throw AbortException("ListLoader::startTag - " + STRING(ABORT_EM));
	}
	
	if (m_is_in_listing)
	{
		if (name == g_SFile)
		{
			dcassert(attribs.size() >= 3); // Иногда есть Shared - 4-тый атрибут.
			// это тэг от грея. его тоже можно обработать и записать в TS. хотя там 64 битное время
			const string& l_name = getAttrib(attribs, g_SName, 0);
			if (l_name.empty())
			{
				dcassert(0);
				return;
			}
			
			const string& l_s = getAttrib(attribs, g_SSize, 1);
			if (l_s.empty())
			{
				dcassert(0);
				return;
			}
			const auto l_size = Util::toInt64(l_s);
			
			const string& l_h = getAttrib(attribs, g_STTH, 2);
			
			if (l_h.empty() || (m_is_own_list == false && l_h.compare(0, 39, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 39) == 0))
			{
				//dcassert(0);
				return;
			}
			const TTHValue l_tth(l_h); /// @todo verify validity?
			dcassert(l_tth != TTHValue());
			
			if (m_is_updating)
			{
				// just update the current file if it is already there.
				for (auto i = m_cur->m_files.cbegin(); i != m_cur->m_files.cend(); ++i)
				{
					auto& file = **i;
					/// @todo comparisons should be case-insensitive but it takes too long - add a cache
					if (file.getName() == l_name || file.getTTH() == l_tth)
					{
						file.setName(l_name);
						file.setSize(l_size);
						file.setTTH(l_tth);
						return;
					}
				}
			}
			// [+] FlylinkDC
			std::shared_ptr<CFlyMediaInfo> l_mediaXY;
			uint32_t l_i_ts = 0;
			int l_i_hit     = 0;
			string l_hit;
#ifdef FLYLINKDC_USE_DIRLIST_FILE_EXT_STAT
			auto& l_item = DirectoryListing::g_ext_stat[Util::getFileExtWithoutDot(Text::toLower(l_name))];
			l_item.m_count++;
			if (l_size > l_item.m_max_size)
				l_item.m_max_size = l_size;
			if (l_size < l_item.m_min_size)
				l_item.m_min_size = l_size;
				
#endif
			if (attribs.size() >= 4) // 3 - стандартный DC++, 4 - GreyLinkDC++
			{
				if (attribs.size() == 4 ||
				        attribs.size() >= 11)  // Хитрый расширенный формат от http://p2p.toom.su/fs/hms/FCYECUWQ7F5A2FABW32UTMCT6MEMI3GPXBZDQCQ/)
				{
					const string l_sharedGL = getAttrib(attribs, g_SShared, 4);
					if (!l_sharedGL.empty())
					{
						const int64_t tmp_ts = _atoi64(l_sharedGL.c_str()) - 116444736000000000L ;
						if (tmp_ts <= 0L)
							l_i_ts = 0;
						else
							l_i_ts = uint32_t(tmp_ts / 10000000L);
					}
				}
				string l_ts;
				if (l_i_ts == 0)
				{
					l_ts = getAttrib(attribs, g_STS, 3); // TODO проверить  attribs.size() >= 4 если = 4 или 3 то TS нет и можно не искать
				}
				if (!m_is_first_check_mediainfo_list)
				{
					m_is_first_check_mediainfo_list = true;
					m_is_mediainfo_list = !l_ts.empty();
				}
				if (!l_ts.empty()  // Extended tags - exists only FlylinkDC++ or StrongDC++ sqlite or clones
				        || l_i_ts // Грейлинк - время расшаривания
				   )
				{
					if (!l_ts.empty())
					{
						l_i_ts = atoi(l_ts.c_str());
					}
					
					if (attribs.size() > 4) // TODO - собрать комбинации всех случаев
					{
						l_hit = getAttrib(attribs, g_SHit, 3);
						const std::string& l_audio = getAttrib(attribs, g_SMAudio, 3);
						const std::string& l_video = getAttrib(attribs, g_SMVideo, 3);
						if (!l_audio.empty() || !l_video.empty())
						{
							const string& l_br = getAttrib(attribs, g_SBR, 4);
							l_mediaXY = std::make_shared<CFlyMediaInfo>(getAttrib(attribs, g_SWH, 3),
							                                            atoi(l_br.c_str()),
							                                            l_audio,
							                                            l_video
							                                           );
						}
					}
					
#if 0
					if (attribs.size() > 4) // TODO - собрать комбинации всех случаев
					{
						CFlyMediainfoRAW l_media_item;
						{
							l_media_item.m_audio = getAttrib(attribs, g_SMAudio, 3);
							const size_t l_pos = l_media_item.m_audio.find('|', 0);
							if (l_pos != string::npos && l_pos)
							{
								if (l_pos + 2 < l_media_item.m_audio.length())
								{
									l_media_item.m_audio = l_media_item.m_audio.substr(l_pos + 2);
								}
							}
						}
						
						l_media_item.m_video = getAttrib(attribs, g_SMVideo, 3);
						l_hit = getAttrib(attribs, g_SHit, 3);
						l_media_item.m_WH = getAttrib(attribs, g_SWH, 3);
						if (!l_media_item.m_audio.empty() || !l_media_item.m_video.empty())
						{
							l_media_item.m_br = getAttrib(attribs, g_SBR, 4);
							auto& l_find_mi = g_cache_mediainfo[l_media_item];
							if (!l_find_mi)
							{
							
								l_find_mi = std::make_shared<CFlyMediaInfo>(l_media_item.m_WH,
								                                            atoi(l_media_item.m_br.c_str()),
								                                            l_media_item.m_audio,
								                                            l_media_item.m_video
								                                           );
								l_mediaXY = l_find_mi;
							}
						}
					}
#endif
				}
				l_i_hit = l_hit.empty() ? 0 : atoi(l_hit.c_str());
			}
			auto f = new DirectoryListing::File(m_cur, l_name, l_size, l_tth, l_i_hit, l_i_ts, l_mediaXY);
			m_cur->m_virus_detect.add(l_name, l_size);
			m_cur->m_files.push_back(f);
			if (l_size)
			{
				if (m_is_own_list)//[+] FlylinkDC++
				{
					f->setFlag(DirectoryListing::FLAG_SHARED_OWN);  // TODO - убить FLAG_SHARED_OWN
				}
				else
				{
					if (ShareManager::isTTHShared(f->getTTH()))
					{
						f->setFlag(DirectoryListing::FLAG_SHARED);
					}
					else
					{
						if (QueueManager::is_queue_tth(f->getTTH()))
						{
							f->setFlag(DirectoryListing::FLAG_QUEUE);
						}
						// TODO if(l_size >= 100 * 1024 *1024)
						{
							if (!CFlyServerConfig::isParasitFile(f->getName())) // TODO - опимизнуть по расширениям
							{
								f->setFlag(DirectoryListing::FLAG_NOT_SHARED);
								const auto l_status_file = CFlylinkDBManager::getInstance()->get_status_file(f->getTTH()); // TODO - унести в отдельную нитку?
								if (l_status_file & CFlylinkDBManager::PREVIOUSLY_DOWNLOADED)
									f->setFlag(DirectoryListing::FLAG_DOWNLOAD);
								if (l_status_file & CFlylinkDBManager::VIRUS_FILE_KNOWN)
									f->setFlag(DirectoryListing::FLAG_VIRUS_FILE);
								if (l_status_file & CFlylinkDBManager::PREVIOUSLY_BEEN_IN_SHARE)
									f->setFlag(DirectoryListing::FLAG_OLD_TTH);
							}
						}
					}
				}//[+] FlylinkDC++
			}
		}
		else if (name == g_SDirectory)
		{
			string l_file_name = getAttrib(attribs, g_SName, 0);
			if (l_file_name.empty())
			{
				//  throw SimpleXMLException("Directory missing name attribute");
				l_file_name = "empty_file_name_" + Util::toString(++m_empty_file_name_counter);
			}
			const bool incomp = getAttrib(attribs, sIncomplete, 1) == "1";
			DirectoryListing::Directory* d = nullptr;
			if (m_is_updating)
			{
				for (auto i  = m_cur->directories.cbegin(); i != m_cur->directories.cend(); ++i)
				{
					/// @todo comparisons should be case-insensitive but it takes too long - add a cache
					if ((*i)->getName() == l_file_name)
					{
						d = *i;
						if (!d->getComplete())
						{
							d->setComplete(!incomp);
						}
						break;
					}
				}
			}
			if (d == nullptr)
			{
				d = new DirectoryListing::Directory(m_list, m_cur, l_file_name, false, !incomp, isMediainfoList());
				m_cur->directories.push_back(d);
			}
			m_cur = d;
			
			if (simple)
			{
				// To handle <Directory Name="..." />
				endTag(name, Util::emptyString);
			}
		}
	}
	else if (name == sFileListing)
	{
		const string& b = getAttrib(attribs, sBase, 2);
		if (b.size() >= 1 && b[0] == '/' && b[b.size() - 1] == '/')
		{
			m_base = b;
		}
		if (m_base.size() > 1) // [+]PPA fix for [4](("Version", "1"),("CID", "EDI7OWB6TZWH6X6L2D3INC6ORQSG6RQDJ6AJ5QY"),("Base", "/"),("Generator", "DC++ 0.785"))
		{
			const StringTokenizer<string> sl(m_base.substr(1), '/');
			for (auto i = sl.getTokens().cbegin(); i != sl.getTokens().cend(); ++i)
			{
				DirectoryListing::Directory* d = nullptr;
				for (auto j = m_cur->directories.cbegin(); j != m_cur->directories.cend(); ++j)
				{
					if ((*j)->getName() == *i)
					{
						d = *j;
						break;
					}
				}
				if (d == nullptr)
				{
					d = new DirectoryListing::Directory(m_list, m_cur, *i, false, false, isMediainfoList());
					m_cur->directories.push_back(d);
				}
				m_cur = d;
			}
		}
		m_cur->setComplete(true);
		
		// [+] IRainman Delayed loading (dclst support)
		const string& l_cidStr = getAttrib(attribs, sCID, 2);
		if (l_cidStr.size() == 39)
		{
			const CID l_CID(l_cidStr);
			if (!l_CID.isZero())
			{
				if (!m_user)
				{
					m_user = ClientManager::createUser(l_CID, "", 0);
					m_list->setHintedUser(HintedUser(m_user, Util::emptyString));
				}
			}
		}
		const string& l_getIncludeSelf = getAttrib(attribs, sIncludeSelf, 2);
		m_list->setIncludeSelf(l_getIncludeSelf == "1");
		// [~] IRainman Delayed loading (dclst support)
		
		m_is_in_listing = true;
		
		if (simple)
		{
			// To handle <Directory Name="..." />
			endTag(name, Util::emptyString);
		}
	}
}
Beispiel #18
0
void SearchManager::onData(const string& x, const string& remoteIp) {
	if(x.compare(0, 4, "$SR ") == 0) {
		string::size_type i, j;
		// Directories: $SR <nick><0x20><directory><0x20><free slots>/<total slots><0x05><Hubname><0x20>(<Hubip:port>)
		// Files:		$SR <nick><0x20><filename><0x05><filesize><0x20><free slots>/<total slots><0x05><Hubname><0x20>(<Hubip:port>)
		i = 4;
		if( (j = x.find(' ', i)) == string::npos) {
			return;
		}
		string nick = x.substr(i, j-i);
		i = j + 1;

		// A file has 2 0x05, a directory only one
		size_t cnt = count(x.begin() + j, x.end(), 0x05);

		SearchResult::Types type = SearchResult::TYPE_FILE;
		string file;
		int64_t size = 0;

		if(cnt == 1) {
			// We have a directory...find the first space beyond the first 0x05 from the back
			// (dirs might contain spaces as well...clever protocol, eh?)
			type = SearchResult::TYPE_DIRECTORY;
			// Get past the hubname that might contain spaces
			if((j = x.rfind(0x05)) == string::npos) {
				return;
			}
			// Find the end of the directory info
			if((j = x.rfind(' ', j-1)) == string::npos) {
				return;
			}
			if(j < i + 1) {
				return;
			}
			file = x.substr(i, j-i) + '\\';
		} else if(cnt == 2) {
			if( (j = x.find((char)5, i)) == string::npos) {
				return;
			}
			file = x.substr(i, j-i);
			i = j + 1;
			if( (j = x.find(' ', i)) == string::npos) {
				return;
			}
			size = Util::toInt64(x.substr(i, j-i));
		}
		i = j + 1;

		if( (j = x.find('/', i)) == string::npos) {
			return;
		}
		int freeSlots = Util::toInt(x.substr(i, j-i));
		i = j + 1;
		if( (j = x.find((char)5, i)) == string::npos) {
			return;
		}
		int slots = Util::toInt(x.substr(i, j-i));
		i = j + 1;
		if( (j = x.rfind(" (")) == string::npos) {
			return;
		}
		string hubName = x.substr(i, j-i);
		i = j + 2;
		if( (j = x.rfind(')')) == string::npos) {
			return;
		}

		HintedUser user;

		user.hint = ClientManager::getInstance()->findHub(x.substr(i, j - i));
		if(user.hint.empty()) {
			// Could happen if hub has multiple URLs / IPs
			user = ClientManager::getInstance()->findLegacyUser(nick);
			if(!user)
				return;
		}

		string encoding = ClientManager::getInstance()->findHubEncoding(user.hint);
		nick = Text::toUtf8(nick, encoding);
		file = Text::toUtf8(file, encoding);
		hubName = Text::toUtf8(hubName, encoding);

		if(!user) {
			user.user = ClientManager::getInstance()->findUser(nick, user.hint);
			if(!user)
				return;
		}

		string tth;
		if(hubName.compare(0, 4, "TTH:") == 0) {
			tth = hubName.substr(4);
			StringList names = ClientManager::getInstance()->getHubNames(user);
			hubName = names.empty() ? _("Offline") : Util::toString(names);
		}

		if(tth.empty() && type == SearchResult::TYPE_FILE) {
			return;
		}

		fire(SearchManagerListener::SR(), SearchResultPtr(new SearchResult(user, type, slots,
			freeSlots, size, file, hubName, remoteIp, TTHValue(tth), Util::emptyString)));

	} else if(x.compare(1, 4, "RES ") == 0 && x[x.length() - 1] == 0x0a) {
		AdcCommand c(x.substr(0, x.length()-1));
		if(c.getParameters().empty())
			return;
		string cid = c.getParam(0);
		if(cid.size() != 39)
			return;

		UserPtr user = ClientManager::getInstance()->findUser(CID(cid));
		if(!user)
			return;

		// This should be handled by AdcCommand really...
		c.getParameters().erase(c.getParameters().begin());

		onRES(c, user, remoteIp);

	} /*else if(x.compare(1, 4, "SCH ") == 0 && x[x.length() - 1] == 0x0a) {
		try {
			respond(AdcCommand(x.substr(0, x.length()-1)));
		} catch(ParseException& ) {
		}
	}*/ // Needs further DoS investigation
}
bool UploadManager::prepareFile(UserConnection& aSource, const string& aType, const string& aFile, int64_t aStartPos, int64_t aBytes, bool listRecursive) {
	if(aFile.empty() || aStartPos < 0 || aBytes < -1 || aBytes == 0) {
		aSource.fileNotAvail("Invalid request");
		return false;
	}

	InputStream* is = 0;
	int64_t start = 0;
	int64_t bytesLeft = 0;
	int64_t size = 0;

	bool userlist = (aFile == Transfer::USER_LIST_NAME_BZ || aFile == Transfer::USER_LIST_NAME);
	bool free = userlist;
	bool leaves = false;
	bool partList = false;

	string sourceFile;
	try {
		if(aType == Transfer::TYPE_FILE) {
			sourceFile = ShareManager::getInstance()->toReal(aFile);

			if(aFile == Transfer::USER_LIST_NAME) {
				// Unpack before sending...
				string bz2 = File(sourceFile, File::READ, File::OPEN).read();
				string xml;
				CryptoManager::getInstance()->decodeBZ2(reinterpret_cast<const uint8_t*>(bz2.data()), bz2.size(), xml);
				// Clear to save some memory...
				string().swap(bz2);
				is = new MemoryInputStream(xml);
				start = 0;
				bytesLeft = size = xml.size();
			} else {
				File* f = new File(sourceFile, File::READ, File::OPEN);

				start = aStartPos;
				size = f->getSize();
				bytesLeft = (aBytes == -1) ? size : aBytes;

				if(size < (start + bytesLeft)) {
					aSource.fileNotAvail();
					delete f;
					return false;
				}

				free = free || (size <= (int64_t)(SETTING(FREE_SLOTS_SIZE) * 1024) );

				f->setPos(start);

				is = f;
				if((start + bytesLeft) < size) {
					is = new LimitedInputStream<true>(is, aBytes);
				}
			}
		} else if(aType == Transfer::TYPE_TTHL) {
			sourceFile = ShareManager::getInstance()->toReal(aFile);
			MemoryInputStream* mis = ShareManager::getInstance()->getTree(aFile);
			if(!mis) {
				aSource.fileNotAvail();
				return false;
			}

			start = 0;
			bytesLeft = size = mis->getSize();
			is = mis;
			leaves = true;
			free = true;
		} else {
			aSource.fileNotAvail("Unknown file type");
			return false;
		}
	} catch(const ShareException& e) {
		aSource.fileNotAvail(e.getError());
		return false;
	} catch(const Exception& e) {
		LogManager::getInstance()->message(STRING(UNABLE_TO_SEND_FILE) + sourceFile + ": " + e.getError());
		aSource.fileNotAvail();
		return false;
	}

	Lock l(cs);

	bool extraSlot = false;

	if(!aSource.isSet(UserConnection::FLAG_HASSLOT)) {
		bool hasReserved = (reservedSlots.find(aSource.getUser()) != reservedSlots.end());
		bool isFavorite = aSource.getUser()->getFavoriteGrantSlot();

		if(!(hasReserved || isFavorite || getFreeSlots() > 0 || getAutoSlot())) {
			bool supportsFree = aSource.isSet(UserConnection::FLAG_SUPPORTS_MINISLOTS);
			bool allowedFree = aSource.isSet(UserConnection::FLAG_HASEXTRASLOT) || aSource.isSet(UserConnection::FLAG_OP) || getFreeExtraSlots() > 0;
			if(free && supportsFree && allowedFree) {
				extraSlot = true;
			} else {
				delete is;
				aSource.maxedOut();

				// Check for tth root identifier
				string tFile = aFile;
				if (tFile.compare(0, 4, "TTH/") == 0)
					tFile = ShareManager::getInstance()->toVirtual(TTHValue(aFile.substr(4)));

				addFailedUpload(aSource, tFile +
					" (" + Util::toString((aStartPos*1000/(size+10))/10.0)+"% of " + Util::formatBytes(size) + " done)");
				aSource.disconnect();
				return false;
			}
		} else {
			clearUserFiles(aSource.getUser());	// this user is using a full slot, nix them.
		}

		setLastGrant(GET_TICK());
	}

	Upload* u = new Upload(aSource);
	u->setStream(is);
	if(aBytes == -1)
		u->setSize(size);
	else
		u->setSize(start + bytesLeft);

	u->setStartPos(start);
	u->setSourceFile(sourceFile);

	if(userlist)
		u->setFlag(Upload::FLAG_USER_LIST);
	if(leaves)
		u->setFlag(Upload::FLAG_TTH_LEAVES);
	if(partList)
		u->setFlag(Upload::FLAG_PARTIAL_LIST);

	uploads.push_back(u);

	if(!aSource.isSet(UserConnection::FLAG_HASSLOT)) {
		if(extraSlot) {
			if(!aSource.isSet(UserConnection::FLAG_HASEXTRASLOT)) {
				aSource.setFlag(UserConnection::FLAG_HASEXTRASLOT);
				extra++;
			}
		} else {
			if(aSource.isSet(UserConnection::FLAG_HASEXTRASLOT)) {
				aSource.unsetFlag(UserConnection::FLAG_HASEXTRASLOT);
				extra--;
			}
			aSource.setFlag(UserConnection::FLAG_HASSLOT);
			running++;
		}

		reservedSlots.erase(aSource.getUser());
	}

	return true;
}
Beispiel #20
0
void SearchManager::onPSR(const AdcCommand& cmd, UserPtr from, const string& remoteIp) {

        uint16_t udpPort = 0;
        uint32_t partialCount = 0;
        string tth;
        string hubIpPort;
        string nick;
        PartsInfo partialInfo;

        for(StringIterC i = cmd.getParameters().begin(); i != cmd.getParameters().end(); ++i) {
                const string& str = *i;
                if(str.compare(0, 2, "U4") == 0) {
                        udpPort = static_cast<uint16_t>(Util::toInt(str.substr(2)));
                } else if(str.compare(0, 2, "NI") == 0) {
                        nick = str.substr(2);
                } else if(str.compare(0, 2, "HI") == 0) {
                        hubIpPort = str.substr(2);
                } else if(str.compare(0, 2, "TR") == 0) {
                        tth = str.substr(2);
                } else if(str.compare(0, 2, "PC") == 0) {
                        partialCount = Util::toUInt32(str.substr(2))*2;
                } else if(str.compare(0, 2, "PI") == 0) {
                        StringTokenizer<string> tok(str.substr(2), ',');
                        for(StringIter i = tok.getTokens().begin(); i != tok.getTokens().end(); ++i) {
                                partialInfo.push_back((uint16_t)Util::toInt(*i));
                        }
                }
        }

        string url = ClientManager::getInstance()->findHub(hubIpPort);
        if(!from || from == ClientManager::getInstance()->getMe()) {
                // for NMDC support

                if(nick.empty() || hubIpPort.empty()) {
                        return;
                }

                from = ClientManager::getInstance()->findUser(nick, url);
                if(!from) {
                        // Could happen if hub has multiple URLs / IPs
                        from = ClientManager::getInstance()->findLegacyUser(nick);
                        if(!from) {
                                dcdebug("Search result from unknown user");
                                return;
                        }
                }
        }

        //ClientManager::getInstance()->setIPUser(from, remoteIp, udpPort);

        if(partialInfo.size() != partialCount) {
                // what to do now ? just ignore partial search result :-/
                return;
        }

        PartsInfo outPartialInfo;
        QueueItem::PartialSource ps(from->isNMDC() ? ClientManager::getInstance()->getClient(url)->getMyIdentity().getNick() : Util::emptyString, hubIpPort, remoteIp, udpPort);
        ps.setPartialInfo(partialInfo);

        QueueManager::getInstance()->handlePartialResult(from, url, TTHValue(tth), ps, outPartialInfo);

        if((udpPort > 0) && !outPartialInfo.empty()) {
                try {
                        AdcCommand cmd = SearchManager::getInstance()->toPSR(false, ps.getMyNick(), hubIpPort, tth, outPartialInfo);
                        ClientManager::getInstance()->send(cmd, from->getCID());
                } catch(...) {
                        dcdebug("Partial search caught error\n");
                }
        }

}
Beispiel #21
0
/**
 * 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; }
	}
}