📄 searchlist.cpp
字号:
Debug(_T("*** NOTE: Client ProcessSearchanswer(%s): ***AddData: 1 byte: 0x%02x\n"), Sender->GetUserName(), ucMore);
}
}
else if (iAddData > 0){
if (thePrefs.GetDebugClientTCPLevel() > 0){
Debug(_T("*** NOTE: Client ProcessSearchanswer(%s): ***AddData: %u bytes\n"), Sender->GetUserName(), iAddData);
DebugHexDump((uint8*)in_packet + packet.GetPosition(), iAddData);
}
}
packet.Close();
return GetResultCount(nSearchID);
}
uint16 CSearchList::ProcessSearchanswer(char* in_packet, uint32 size,
uint32 nServerIP, uint16 nServerPort, bool* pbMoreResultsAvailable)
{
CSafeMemFile packet((BYTE*)in_packet,size);
UINT results = packet.ReadUInt32();
for (UINT i = 0; i < results; i++){
CSearchFile* toadd = new CSearchFile(&packet, m_nCurrentSearch);
toadd->SetClientServerIP(nServerIP);
toadd->SetClientServerPort(nServerPort);
if (nServerIP && nServerPort){
CSearchFile::SServer server(nServerIP, nServerPort);
server.m_uAvail = toadd->GetIntTagValue(FT_SOURCES);
toadd->AddServer(server);
}
AddToList(toadd, false);
}
if (m_MobilMuleSearch)
theApp.mmserver->SearchFinished(false);
m_MobilMuleSearch = false;
if (pbMoreResultsAvailable)
*pbMoreResultsAvailable = false;
int iAddData = (int)(packet.GetLength() - packet.GetPosition());
if (iAddData == 1){
uint8 ucMore = packet.ReadUInt8();
if (ucMore == 0x00 || ucMore == 0x01){
if (pbMoreResultsAvailable)
*pbMoreResultsAvailable = (bool)ucMore;
if (thePrefs.GetDebugServerTCPLevel() > 0)
Debug(_T(" Search answer(Server %s:%u): More=%u\n"), ipstr(nServerIP), nServerPort, ucMore);
}
else{
if (thePrefs.GetDebugServerTCPLevel() > 0)
Debug(_T("*** NOTE: ProcessSearchanswer(Server %s:%u): ***AddData: 1 byte: 0x%02x\n"), ipstr(nServerIP), nServerPort, ucMore);
}
}
else if (iAddData > 0){
if (thePrefs.GetDebugServerTCPLevel() > 0){
Debug(_T("*** NOTE: ProcessSearchanswer(Server %s:%u): ***AddData: %u bytes\n"), ipstr(nServerIP), nServerPort, iAddData);
DebugHexDump((uint8*)in_packet + packet.GetPosition(), iAddData);
}
}
packet.Close();
return GetResultCount();
}
uint16 CSearchList::ProcessUDPSearchanswer(CFileDataIO& packet, uint32 nServerIP, uint16 nServerPort)
{
CSearchFile* toadd = new CSearchFile(&packet, m_nCurrentSearch, nServerIP, nServerPort);
AddToList(toadd);
return GetResultCount();
}
uint16 CSearchList::GetResultCount(uint32 nSearchID) const
{
uint16 nSources = 0;
VERIFY( m_foundSourcesCount.Lookup(nSearchID, nSources) );
return nSources;
}
uint16 CSearchList::GetResultCount() const {
return GetResultCount(m_nCurrentSearch);
}
CString CSearchList::GetWebList(CString linePattern,int sortby,bool asc) const {
CString buffer;
CString temp;
CArray<CSearchFile*, CSearchFile*> sortarray;
int swap = 0;
bool inserted;
// insertsort
CSearchFile* sf1;
CSearchFile* sf2;
for (POSITION pos = list.GetHeadPosition(); pos !=0;) {
inserted=false;
sf1 = list.GetNext(pos);
if (sf1->GetListParent()!=NULL) continue;
for (uint16 i1=0;i1<sortarray.GetCount();++i1) {
sf2 = sortarray.GetAt(i1);
switch (sortby) {
case 0: swap=sf1->GetFileName().CompareNoCase(sf2->GetFileName()); break;
case 1: swap=sf1->GetFileSize()-sf2->GetFileSize();break;
case 2: swap=CString(sf1->GetFileHash()).CompareNoCase(CString(sf2->GetFileHash())); break;
case 3: swap=sf1->GetSourceCount()-sf2->GetSourceCount(); break;
}
if (!asc) swap=0-swap;
if (swap<0) {inserted=true; sortarray.InsertAt(i1,sf1);break;}
}
if (!inserted) sortarray.Add(sf1);
}
for (uint16 i=0;i<sortarray.GetCount();++i) {
const CSearchFile* sf = sortarray.GetAt(i);
// colorize
CString coloraddon;
CString coloraddonE;
CKnownFile* sameFile = theApp.sharedfiles->GetFileByID(sf->GetFileHash());
if (!sameFile)
sameFile = theApp.downloadqueue->GetFileByID(sf->GetFileHash());
if (sameFile) {
if (sameFile->IsPartFile())
coloraddon = _T("<font color=\"#FF0000\">");
else
coloraddon = _T("<font color=\"#00FF00\">");
}
if (coloraddon.GetLength()>0)
coloraddonE = _T("</font>");
CString strHash(EncodeBase16(sf->GetFileHash(),16));
temp.Format(linePattern,
coloraddon + StringLimit(sf->GetFileName(),70) + coloraddonE,
CastItoXBytes(sf->GetFileSize()),
strHash,
sf->GetSourceCount(),
strHash);
buffer.Append(temp);
}
return buffer;
}
void CSearchList::AddFileToDownloadByHash(const uchar* hash, uint8 cat)
{
for (POSITION pos = list.GetHeadPosition(); pos != 0; )
{
CSearchFile* sf = list.GetNext(pos);
if (!md4cmp(hash, sf->GetFileHash()))
{
theApp.downloadqueue->AddSearchToDownload(sf, 2, cat);
break;
}
}
}
// mobilemule
CSearchFile* CSearchList::DetachNextFile(uint32 nSearchID) {
// the files are NOT deleted, make sure you do this if you call this function
// find, removes and returns the searchresult with most Sources
uint32 nHighSource = 0;
POSITION resultpos = 0;
for (POSITION pos = list.GetHeadPosition(); pos != NULL; ){
POSITION cur_pos = pos;
CSearchFile* cur_file = list.GetNext(pos);
if( cur_file->GetSearchID() == nSearchID ){
if(cur_file->GetIntTagValue(FT_SOURCES) >= nHighSource){
nHighSource = cur_file->GetIntTagValue(FT_SOURCES);
resultpos = cur_pos;
}
}
}
if (resultpos == 0){
ASSERT ( false );
return NULL;
}
CSearchFile* result = list.GetAt(resultpos);
list.RemoveAt(resultpos);
return result;
}
bool CSearchList::AddToList(CSearchFile* toadd, bool bClientResponse)
{
if (!bClientResponse && !m_strResultFileType.IsEmpty() && strcmp(m_strResultFileType, toadd->GetFileType()) != 0)
{
delete toadd;
return false;
}
for (POSITION pos = list.GetHeadPosition(); pos != NULL; )
{
CSearchFile* cur_file = list.GetNext(pos);
if ( (!md4cmp(toadd->GetFileHash(), cur_file->GetFileHash()))
&& cur_file->GetSearchID() == toadd->GetSearchID()
&& cur_file->GetListParent() == NULL
)
{
UINT uAvail;
if (bClientResponse)
{
// If this is a response from a client ("View Shared Files"), we set the "Availability" at least to 1.
if (!toadd->GetIntTagValue(FT_SOURCES, uAvail) || uAvail==0)
uAvail = 1;
}
else
uAvail = toadd->GetIntTagValue(FT_SOURCES);
// already a result in list (parent exists)
cur_file->AddSources(uAvail);
AddResultCount(cur_file->GetSearchID(), toadd->GetFileHash(), uAvail);
uint32 uCompleteSources = -1;
if (toadd->GetIntTagValue(FT_COMPLETE_SOURCES, uCompleteSources))
cur_file->AddCompleteSources(uCompleteSources);
// check if child with same filename exists
bool found = false;
for (POSITION pos2 = list.GetHeadPosition(); pos2 != NULL && !found; )
{
CSearchFile* cur_file2 = list.GetNext(pos2);
if ( cur_file2 != toadd // not the same object
&& cur_file2->GetListParent() == cur_file // is a child of our result (one filehash)
&& !toadd->GetFileName().CompareNoCase(cur_file2->GetFileName())) // same name
{
if (toadd->IsKademlia())
{
if (uAvail == cur_file2->GetIntTagValue(FT_SOURCES))
{
delete toadd;
return false;
}
}
else
{
// yes: add the counter of that child
found = true;
cur_file2->SetListAddChildCount(uAvail);
cur_file2->AddSources(uAvail);
if (uCompleteSources != -1)
cur_file2->AddCompleteSources(uCompleteSources);
// copy servers to child item -- this is not really needed because the servers are also stored
// in the parent item, but it gives a correct view of the server list within the server property page
for (int s = 0; s < toadd->GetServers().GetSize(); s++)
{
CSearchFile::SServer server = toadd->GetServerAt(s);
int iFound = cur_file2->GetServers().Find(server);
if (iFound == -1)
cur_file2->AddServer(server);
else
cur_file2->GetServerAt(iFound).m_uAvail += server.m_uAvail;
}
break;
}
}
}
if (!found)
{
// no: add child
toadd->SetListParent(cur_file);
toadd->SetListChildCount(uAvail);
cur_file->SetListAddChildCount(1);
list.AddHead(toadd);
}
outputwnd->UpdateSources(cur_file);
if ((toadd->GetClientID() && toadd->GetClientPort()))
{
if (IsValidClientIPPort(toadd->GetClientID(), toadd->GetClientPort()))
{
// pre-filter sources which would be dropped in CPartFile::AddSources
if (CPartFile::CanAddSource(toadd->GetClientID(), toadd->GetClientPort(), toadd->GetClientServerIP(), toadd->GetClientServerPort()))
{
CSearchFile::SClient client(toadd->GetClientID(), toadd->GetClientPort(),
toadd->GetClientServerIP(), toadd->GetClientServerPort());
if (cur_file->GetClients().Find(client) == -1)
cur_file->AddClient(client);
}
}
else
{
if (thePrefs.GetDebugServerSearchesLevel() > 1)
{
uint32 nIP = toadd->GetClientID();
Debug(_T("Filtered source from search result %s:%u\n"), DbgGetClientID(nIP), toadd->GetClientPort());
}
}
}
// will be used in future
if (toadd->GetClientServerIP() && toadd->GetClientServerPort())
{
CSearchFile::SServer server(toadd->GetClientServerIP(), toadd->GetClientServerPort());
int iFound = cur_file->GetServers().Find(server);
if (iFound == -1)
{
server.m_uAvail = uAvail;
cur_file->AddServer(server);
}
else
cur_file->GetServerAt(iFound).m_uAvail += uAvail;
}
if (outputwnd && !m_MobilMuleSearch)
outputwnd->UpdateSources(cur_file);
if (found)
delete toadd;
return true;
}
}
// no bounded result found yet -> add as parent to list
toadd->SetListParent(NULL);
if (list.AddTail(toadd))
{
uint16 tempValue = 0;
VERIFY( m_foundFilesCount.Lookup(toadd->GetSearchID(),tempValue) );
m_foundFilesCount.SetAt(toadd->GetSearchID(),tempValue+1);
// new search result entry (no parent); add to result count for search result limit
UINT uAvail;
if (bClientResponse)
{
// If this is a response from a client ("View Shared Files"), we set the "Availability" at least to 1.
if (!toadd->GetIntTagValue(FT_SOURCES, uAvail) || uAvail==0)
uAvail = 1;
toadd->AddSources(uAvail);
}
else
uAvail = toadd->GetIntTagValue(FT_SOURCES);
AddResultCount(toadd->GetSearchID(), toadd->GetFileHash(), uAvail);
CSearchFile* neu = new CSearchFile(toadd);
neu->SetListParent(toadd);
neu->SetListChildCount(uAvail);
list.AddTail(neu);
toadd->SetListChildCount(1);
}
if (outputwnd && !m_MobilMuleSearch)
outputwnd->AddResult(toadd);
return true;
}
CSearchFile* CSearchList::GetSearchFileByHash(const uchar* hash) const
{
for (POSITION pos = list.GetHeadPosition(); pos != 0; )
{
CSearchFile* sf = list.GetNext(pos);
if (!md4cmp(hash, sf->GetFileHash()))
return sf;
}
return NULL;
}
void CSearchList::AddResultCount(uint32 nSearchID, const uchar* hash, UINT nCount)
{
// do not count already available or downloading files for the search result limit
if (theApp.sharedfiles->GetFileByID(hash) || theApp.downloadqueue->GetFileByID(hash))
return;
uint16 tempValue = 0;
VERIFY( m_foundSourcesCount.Lookup(nSearchID, tempValue) );
m_foundSourcesCount.SetAt(nSearchID, tempValue + nCount);
}
void CSearchList::KademliaSearchKeyword(uint32 searchID, const Kademlia::CUInt128* fileID,
LPCTSTR name, uint32 size, LPCTSTR type, uint16 numProperties, ...)
{
va_list args;
va_start(args, numProperties);
CSafeMemFile* temp = new CSafeMemFile(250);
uchar fileid[16];
fileID->toByteArray(fileid);
temp->WriteHash16(fileid);
temp->WriteUInt32(0); // client IP
temp->WriteUInt16(0); // client port
// write tag list
UINT uFilePosTagCount = temp->GetPosition();
uint32 tagcount = 0;
temp->WriteUInt32(tagcount); // dummy tag count, will be filled later
// standard tags
CTag tagName(FT_FILENAME, name);
tagName.WriteTagToFile(temp);
tagcount++;
CTag tagSize(FT_FILESIZE, size);
tagSize.WriteTagToFile(temp);
tagcount++;
if (type != NULL && type[0] != _T('\0'))
{
CTag tagType(FT_FILETYPE, type);
tagType.WriteTagToFile(temp);
tagcount++;
}
// additional tags
while (numProperties-- > 0)
{
UINT uPropType = va_arg(args, UINT);
LPCSTR pszPropName = va_arg(args, LPCSTR);
LPVOID pvPropValue = va_arg(args, LPVOID);
if (uPropType == 2 /*TAGTYPE_STRING*/)
{
if ((LPCTSTR)pvPropValue != NULL && ((LPCTSTR)pvPropValue)[0] != _T('\0'))
{
if (strlen(pszPropName) == 1)
{
CTag tagProp((uint8)*pszPropName, (LPCTSTR)pvPropValue);
tagProp.WriteTagToFile(temp);
}
else
{
CTag tagProp(pszPropName, (LPCTSTR)pvPropValue);
tagProp.WriteTagToFile(temp);
}
tagcount++;
}
}
else if (uPropType == 3 /*TAGTYPE_UINT32*/)
{
if ((uint32)pvPropValue != 0)
{
CTag tagProp(pszPropName, (uint32)pvPropValue);
tagProp.WriteTagToFile(temp);
tagcount++;
}
}
else
{
ASSERT(0);
}
}
va_end(args);
temp->Seek(uFilePosTagCount, SEEK_SET);
temp->WriteUInt32(tagcount);
temp->SeekToBegin();
CSearchFile* tempFile = new CSearchFile(temp, searchID, 0, 0, 0, true);
AddToList(tempFile);
delete temp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -