2 // This file is part of the aMule Project.
4 // Copyright (c) 2007-2011 Johannes Krampf ( wuischke@amule.org )
8 // Angel Vidal Veiga aka Kry <kry@amule.org>
9 // * changed class names
11 // Marcelo Malheiros <mgmalheiros@gmail.com>
12 // * fixed error with FT_FILEHASH
13 // * added inital 5 tag/file support
15 // Any parts of this program derived from the xMule, lMule or eMule project,
16 // or contributed by third-party developers are copyrighted by their
17 // respective authors.
19 // This program is free software; you can redistribute it and/or modify
20 // it under the terms of the GNU General Public License as published by
21 // the Free Software Foundation; either version 2 of the License, or
22 // (at your option) any later version.
24 // This program is distributed in the hope that it will be useful,
25 // but WITHOUT ANY WARRANTY; without even the implied warranty of
26 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 // GNU General Public License for more details.
29 // You should have received a copy of the GNU General Public License
30 // along with this program; if not, write to the Free Software
31 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
35 #include "MuleCollection.h"
42 bool CMuleCollection::Open(const std::string
&File
)
44 return OpenBinary(File
) || OpenText(File
);
48 template <typename intType
>
49 intType
CMuleCollection::ReadInt(std::ifstream
& infile
)
52 infile
.read(reinterpret_cast<char *>(&integer
),sizeof(intType
));
57 std::string
CMuleCollection::ReadString(std::ifstream
& infile
, int TagType
= 0x02)
59 if (TagType
>= 0x11 && TagType
<= 0x20) {
60 std::vector
<char> buffer(TagType
- 0x10);
61 infile
.read(&buffer
[0], TagType
- 0x10);
62 return buffer
.empty() ?
64 std::string (buffer
.begin(), buffer
.end());
66 if (TagType
== 0x02) {
67 uint16_t TagStringSize
= ReadInt
<uint16_t>(infile
);
68 std::vector
<char> buffer (TagStringSize
);
69 infile
.read(&buffer
[0], TagStringSize
);
70 return buffer
.empty() ?
72 std::string (buffer
.begin(), buffer
.end());
77 bool CMuleCollection::OpenBinary(const std::string
&File
)
81 infile
.open(File
.c_str(), std::ifstream::in
|std::ifstream::binary
);
82 if(!infile
.is_open()) {
86 uint32_t cVersion
= ReadInt
<uint32_t>(infile
);
89 ( cVersion
!= 0x01 && cVersion
!= 0x02)) {
94 uint32_t hTagCount
= ReadInt
<uint32_t>(infile
);
101 for (size_t hTi
= 0; hTi
< hTagCount
;hTi
++) {
102 int hTagType
= infile
.get();
104 // hTagFormat == 1 -> FT-value is given
105 uint16_t hTagFormat
= ReadInt
<uint16_t>(infile
);
106 if (hTagFormat
!= 0x0001) {
111 int hTag
= infile
.get();
112 if (!infile
.good()) {
119 /*std::string fileName =*/ ReadString(infile
, hTagType
);
122 // FT_COLLECTIONAUTHOR
124 /*std::string CollectionAuthor =*/ ReadString(infile
, hTagType
);
127 // FT_COLLECTIONAUTHORKEY
129 uint32_t hTagBlobSize
= ReadInt
<uint32_t>(infile
);
130 if (!infile
.good()) {
134 std::vector
<char> CollectionAuthorKey(hTagBlobSize
);
135 infile
.read(&CollectionAuthorKey
[0], hTagBlobSize
);
140 if (!infile
.good()) {
148 uint32_t cFileCount
= ReadInt
<uint32_t>(infile
);
151 softlimit is set to 1024 to avoid problems with big uint32_t values
152 I don't believe anyone would want to use an emulecollection file
153 to store more than 1024 files, but just raise below value in case
154 you know someone who does.
163 vCollection
.reserve(cFileCount
);
165 for (size_t cFi
= 0; cFi
< cFileCount
; ++cFi
) {
166 uint32_t fTagCount
= ReadInt
<uint32_t>(infile
);
168 if (!infile
.good() ||
174 std::string fileHash
= std::string(32, '0');
175 uint64_t fileSize
= 0;
176 std::string fileName
;
177 std::string rootHash
;
178 for(size_t fTi
= 0; fTi
< fTagCount
; ++fTi
) {
179 int fTagType
= infile
.get();
180 if (!infile
.good()) {
185 int fTag
= infile
.get();
186 if (!infile
.good()) {
194 std::vector
<char> bFileHash(16);
195 infile
.read(&bFileHash
[0], 16);
196 std::string hex
= "0123456789abcdef";
197 for (int pos
= 0; pos
< 16; pos
++) {
198 fileHash
[pos
*2] = hex
[((bFileHash
[pos
] >> 4) & 0xF)];
199 fileHash
[(pos
*2) + 1] = hex
[(bFileHash
[pos
]) & 0x0F];
205 rootHash
= ReadString(infile
, 0x02);
212 fileSize
= ReadInt
<uint32_t>(infile
);
216 fileSize
= ReadInt
<uint16_t>(infile
);
220 fileSize
= infile
.get();
224 fileSize
= ReadInt
<uint64_t>(infile
);
227 default: // Invalid file structure
236 fileName
= ReadString(infile
, fTagType
^0x80);
241 /* std::string FileComment =*/ ReadString(infile
, fTagType
^0x80);
246 if (fTagType
== 0x89) { // TAGTYPE_UINT8
247 // uint8_t FileRating =
262 if( !infile
.good() ) {
268 if (!fileName
.empty() && fileSize
> 0) {
269 std::stringstream link
;
270 // ed2k://|file|fileName|fileSize|fileHash|/
271 link
<< "ed2k://|file|" << fileName
274 if (!rootHash
.empty()) {
275 link
<< "|h=" << rootHash
;
278 vCollection
.push_back(link
.str());
287 bool CMuleCollection::OpenText(const std::string
&File
)
290 std::ifstream infile
;
292 infile
.open(File
.c_str(), std::ifstream::in
|std::ifstream::binary
);
293 if (!infile
.is_open()) {
297 while (getline(infile
, line
, (char)10 /* LF */)) {
298 int last
= line
.size()-1;
299 if ((1 < last
) && ((char)13 /* CR */ == line
.at(last
))) {
302 if (line
.size() > 50 &&
303 line
.substr(0, 13) == "ed2k://|file|" &&
304 line
.substr(line
.size() - 2) == "|/") {
305 vCollection
.push_back(line
);
310 return !vCollection
.empty();