Upstream tarball 20080304
[amule.git] / src / SearchFile.cpp
blob187b489f92a2e95f30e09836bc10bdb32ea0e0e1
1 //
2 // This file is part of the aMule Project.
3 //
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 )
6 //
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
9 // respective authors.
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.
20 //
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)
35 : m_parent(NULL),
36 m_showChildren(false),
37 m_searchID(searchID),
38 m_sourceCount(0),
39 m_completeSourceCount(0),
40 m_kademlia(kademlia),
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()) {
58 case FT_FILENAME:
59 SetFileName(CPath(tag.GetStr()));
60 break;
61 case FT_FILESIZE:
62 SetFileSize(tag.GetInt());
63 break;
64 case FT_FILESIZE_HI:
65 SetFileSize( (((uint64)tag.GetInt()) << 32) + GetFileSize());
66 break;
67 case FT_FILERATING:
68 m_iUserRating = (tag.GetInt() & 0xF) / 3;
69 break;
70 case FT_SOURCES:
71 m_sourceCount = tag.GetInt();
72 break;
73 case FT_COMPLETE_SOURCES:
74 m_completeSourceCount = tag.GetInt();
75 break;
76 default:
77 AddTagUnique(tag);
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)
115 if (m_kademlia) {
116 m_sourceCount = std::max(m_sourceCount, count);
117 m_completeSourceCount = std::max(m_completeSourceCount, count_complete);
118 } else {
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());
142 UpdateParent();
143 Notify_Search_Update_Sources(other);
144 delete file;
145 return;
149 // New unique child.
150 m_children.push_back(file);
151 UpdateParent();
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();
171 index = i;
174 // Create sum of ratings so that the parent contains the avg.
175 if (child->HasRating()) {
176 ratingCount += 1;
177 ratingTotal += child->UserRating();
181 if (ratingCount) {
182 m_iUserRating = (ratingTotal / ratingCount);
185 SetFileName(m_children.at(index)->GetFileName());
187 // File_checked_for_headers