void ClientManager::on(NmdcSearch, Client* aClient, const string& aSeeker, int aSearchType, int64_t aSize, int aFileType, const string& aString) throw() { Speaker<ClientManagerListener>::fire(ClientManagerListener::IncomingSearch(), aString); bool isPassive = (aSeeker.compare(0, 4, "Hub:") == 0); // We don't wan't to answer passive searches if we're in passive mode... if(isPassive && !ClientManager::getInstance()->isActive()) { return; } SearchResult::List l; ShareManager::getInstance()->search(l, aString, aSearchType, aSize, aFileType, aClient, isPassive ? 5 : 10); // dcdebug("Found %d items (%s)\n", l.size(), aString.c_str()); if(l.size() > 0) { if(isPassive) { string name = aSeeker.substr(4); // Good, we have a passive seeker, those are easier... string str; for(SearchResult::Iter i = l.begin(); i != l.end(); ++i) { SearchResult* sr = *i; str += sr->toSR(*aClient); str[str.length()-1] = 5; str += name; str += '|'; sr->decRef(); } if(str.size() > 0) aClient->send(str); } else { try { string ip, file; uint16_t port = 0; Util::decodeUrl(aSeeker, ip, port, file); ip = Socket::resolve(ip); // Temporary fix to avoid spamming hublist.org and dcpp.net if(ip == "70.85.55.252" || ip == "207.44.220.108") { LogManager::getInstance()->message("Someone is trying to use your client to spam " + ip + ", please urge hub owner to fix this"); return; } if(port == 0) port = 412; for(SearchResult::Iter i = l.begin(); i != l.end(); ++i) { SearchResult* sr = *i; udp.writeTo(ip, port, sr->toSR(*aClient)); sr->decRef(); } } catch(const SocketException& /* e */) { dcdebug("Search caught error\n"); } } } }
void SearchManager::onRES(const AdcCommand& cmd, const User::Ptr& 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) { StringList names = ClientManager::getInstance()->getHubNames(from->getCID()); string hubName = names.empty() ? STRING(OFFLINE) : Util::toString(names); StringList hubs = ClientManager::getInstance()->getHubs(from->getCID()); string hub = hubs.empty() ? STRING(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 SearchResult* sr = new SearchResult(from, type, 0, freeSlots, size, file, hubName, hub, remoteIp, TTHValue(tth), token); fire(SearchManagerListener::SR(), sr); sr->decRef(); } }
void SearchManager::onData(const uint8_t* buf, size_t aLen, const string& remoteIp) { string x((char*)buf, aLen); 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; } string hubIpPort = x.substr(i, j-i); string url = ClientManager::getInstance()->findHub(hubIpPort); string encoding = ClientManager::getInstance()->findHubEncoding(url); nick = Text::toUtf8(nick, encoding); file = Text::toUtf8(file, encoding); hubName = Text::toUtf8(hubName, encoding); User::Ptr user = ClientManager::getInstance()->findUser(nick, url); if(!user) { // Could happen if hub has multiple URLs / IPs user = ClientManager::getInstance()->findLegacyUser(nick); if(!user) return; } string tth; if(hubName.compare(0, 4, "TTH:") == 0) { tth = hubName.substr(4); StringList names = ClientManager::getInstance()->getHubNames(user->getCID()); hubName = names.empty() ? STRING(OFFLINE) : Util::toString(names); } if(tth.empty() && type == SearchResult::TYPE_FILE) { return; } SearchResult* sr = new SearchResult(user, type, slots, freeSlots, size, file, hubName, url, remoteIp, TTHValue(tth), Util::emptyString); fire(SearchManagerListener::SR(), sr); sr->decRef(); } 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; User::Ptr 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 }