2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "SearchFile.h" // Interface declarations.
28 #include <tags/FileTags.h>
30 #include "MemFile.h" // Needed for CMemFile
31 #include "Preferences.h" // Needed for thePrefs
32 #include "GuiEvents.h"
34 CSearchFile::CSearchFile(const CMemFile
& data
, bool optUTF8
, wxUIntPtr searchID
, uint32
WXUNUSED(serverIP
), uint16
WXUNUSED(serverPort
), const wxString
& directory
, bool kademlia
)
36 m_showChildren(false),
39 m_completeSourceCount(0),
41 m_directory(directory
)
43 m_abyFileHash
= data
.ReadHash();
44 m_clientID
= data
.ReadUInt32();
45 m_clientPort
= data
.ReadUInt16();
47 if ((!m_clientID
) || (!m_clientPort
)) {
48 m_clientID
= m_clientPort
= 0;
49 } else if (!IsGoodIP(m_clientID
, thePrefs::FilterLanIPs())) {
50 m_clientID
= m_clientPort
= 0;
54 uint32 tagcount
= data
.ReadUInt32();
55 for (unsigned int i
= 0; i
< tagcount
; ++i
) {
56 CTag
tag(data
, optUTF8
);
57 switch (tag
.GetNameID()) {
59 SetFileName(CPath(tag
.GetStr()));
62 SetFileSize(tag
.GetInt());
65 SetFileSize( (((uint64
)tag
.GetInt()) << 32) + GetFileSize());
68 m_iUserRating
= (tag
.GetInt() & 0xF) / 3;
71 m_sourceCount
= tag
.GetInt();
73 case FT_COMPLETE_SOURCES
:
74 m_completeSourceCount
= tag
.GetInt();
81 if (!GetFileName().IsOk()) {
82 throw CInvalidPacket(wxT("No filename in search result"));
87 CSearchFile::CSearchFile(const CSearchFile
& other
)
88 : CAbstractFile(other
),
89 m_parent(other
.m_parent
),
90 m_showChildren(other
.m_showChildren
),
91 m_searchID(other
.m_searchID
),
92 m_sourceCount(other
.m_sourceCount
),
93 m_completeSourceCount(other
.m_completeSourceCount
),
94 m_kademlia(other
.m_kademlia
),
95 m_clientID(other
.m_clientID
),
96 m_clientPort(other
.m_clientPort
),
97 m_directory(other
.m_directory
)
99 for (size_t i
= 0; i
< other
.m_children
.size(); ++i
) {
100 m_children
.push_back(new CSearchFile(*other
.m_children
.at(i
)));
105 CSearchFile::~CSearchFile()
107 for (size_t i
= 0; i
< m_children
.size(); ++i
) {
108 delete m_children
.at(i
);
113 void CSearchFile::AddSources(uint32 count
, uint32 count_complete
)
116 m_sourceCount
= std::max(m_sourceCount
, count
);
117 m_completeSourceCount
= std::max(m_completeSourceCount
, count_complete
);
119 m_sourceCount
+= count
;
120 m_completeSourceCount
+= count_complete
;
125 void CSearchFile::AddChild(CSearchFile
* file
)
127 wxCHECK_RET(file
, wxT("Not a valid child!"));
128 wxCHECK_RET(!file
->GetParent(), wxT("Search-result can only be child of one other result"));
129 wxCHECK_RET(!file
->HasChildren(), wxT("Result already has children, cannot become child."));
130 wxCHECK_RET(!GetParent(), wxT("A child cannot have children of its own"));
131 wxCHECK_RET(GetFileHash() == file
->GetFileHash(), wxT("Mismatching child/parent hashes"));
132 wxCHECK_RET(GetFileSize() == file
->GetFileSize(), wxT("Mismatching child/parent sizes"));
134 file
->m_parent
= this;
136 // TODO: Doesn't handle results with same name but diff. rating.
137 for (size_t i
= 0; i
< m_children
.size(); ++i
) {
138 CSearchFile
* other
= m_children
.at(i
);
140 if (other
->GetFileName() == file
->GetFileName()) {
141 other
->AddSources(file
->GetSourceCount(), file
->GetCompleteSourceCount());
143 Notify_Search_Update_Sources(other
);
150 m_children
.push_back(file
);
153 if (ShowChildren()) {
154 Notify_Search_Add_Result(file
);
159 void CSearchFile::UpdateParent()
161 wxCHECK_RET(!m_parent
, wxT("UpdateParent called on child item"));
163 size_t ratingCount
= 0, ratingTotal
= 0;
164 size_t max
= 0, index
= 0;
165 for (size_t i
= 0; i
< m_children
.size(); ++i
) {
166 const CSearchFile
* child
= m_children
.at(index
);
168 // Locate the most common name
169 if (child
->GetSourceCount() > max
) {
170 max
= child
->GetSourceCount();
174 // Create sum of ratings so that the parent contains the avg.
175 if (child
->HasRating()) {
177 ratingTotal
+= child
->UserRating();
182 m_iUserRating
= (ratingTotal
/ ratingCount
);
185 SetFileName(m_children
.at(index
)->GetFileName());
187 // File_checked_for_headers