2 * © 2008 by David Roden <droden@gmail.com>
7 #include "CollectionReader.h"
8 #include "GlobalSettings.h"
10 CollectionReader::CollectionReader(ReaderInput* readerInput) {
11 this->readerInput = readerInput;
15 CollectionReader::~CollectionReader() {
18 bool CollectionReader::isLineBreakPresent() {
19 size_t indexOfLineBreak = growingBuffer.indexOf('\n');
20 GlobalSettings::isVerbose() && (indexOfLineBreak != (size_t) -1) && fprintf(stderr, "[%s:%d] found line break at %d.\n", __FILE__, __LINE__, indexOfLineBreak);
21 GlobalSettings::isVerbose() && (indexOfLineBreak == (size_t) -1) && fprintf(stderr, "[%s:%d] could not find line break.\n", __FILE__, __LINE__);
22 return indexOfLineBreak != (size_t) -1;
25 StringTag* CollectionReader::readStringTag(bool header) {
28 if (!ensureBufferCapacity(2)) {
31 growingBuffer.read(&unknown, 2);
34 if (!ensureBufferCapacity(1)) {
37 growingBuffer.read(&tagName, 1);
38 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag name %d.\n", __FILE__, __LINE__, tagName);
39 uint16_t tagLength = 0;
40 if (!ensureBufferCapacity(2)) {
43 growingBuffer.read(&tagLength, 2);
44 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag length %d.\n", __FILE__, __LINE__, tagLength);
45 char* tagValue = (char*) malloc(tagLength + 1);
46 if (!ensureBufferCapacity(tagLength) || !tagValue) {
49 growingBuffer.read(tagValue, tagLength);
50 tagValue[tagLength] = '\0';
51 StringTag* stringTag = new StringTag(tagName, tagValue);
56 BlobTag* CollectionReader::readBlobTag(bool header) {
59 if (!ensureBufferCapacity(2)) {
62 growingBuffer.read(&unknown, 2);
65 if (!ensureBufferCapacity(1)) {
68 growingBuffer.read(&tagName, 1);
69 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag name %d.\n", __FILE__, __LINE__, tagName);
70 uint32_t tagLength = 0;
71 if (!ensureBufferCapacity(4)) {
74 growingBuffer.read(&tagLength, 4);
75 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag length %d.\n", __FILE__, __LINE__, tagLength);
76 void* tagValue = (char*) malloc(tagLength);
77 if (!ensureBufferCapacity(tagLength)) {
80 growingBuffer.read(tagValue, tagLength);
81 BlobTag* blobTag = new BlobTag(tagName, tagValue, tagLength);
86 HashTag* CollectionReader::readHashTag() {
87 if (!ensureBufferCapacity(1)) {
91 growingBuffer.read(&tagId, 1);
92 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag id %d.\n", __FILE__, __LINE__, tagId);
93 if (!ensureBufferCapacity(16)) {
97 growingBuffer.read(hash, 16);
98 return new HashTag(tagId, hash);
101 ED2KLink* CollectionReader::getNextLink() {
102 if (readerInput->isEOF() && !growingBuffer.getRemaining()) {
103 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] readInput EOF reached.\n", __FILE__, __LINE__);
107 identifyCollectionType();
108 if (readerInput->isEOF() && !growingBuffer.getRemaining()) {
109 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] readInput EOF reached.\n", __FILE__, __LINE__);
113 if (isTextCollection) {
114 while (!readerInput->isEOF() && !isLineBreakPresent()) {
117 if (readerInput->isEOF() && !growingBuffer.getRemaining()) {
118 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] readInput EOF reached.\n", __FILE__, __LINE__);
121 size_t indexOfLineBreak = growingBuffer.indexOf('\n');
123 if (indexOfLineBreak == (size_t) -1) {
124 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] could not find line break, using remainder of file.\n", __FILE__, __LINE__);
125 indexOfLineBreak = growingBuffer.getRemaining();
126 line = (char*) malloc(indexOfLineBreak + 1);
127 growingBuffer.read(line, indexOfLineBreak);
128 line[indexOfLineBreak] = '\0';
130 line = (char*) malloc(indexOfLineBreak + 1);
131 growingBuffer.read(line, indexOfLineBreak + 1);
132 if (line[indexOfLineBreak] == '\n') {
133 line[indexOfLineBreak] = '\0';
135 if (line[indexOfLineBreak - 1] == '\r') {
136 line[indexOfLineBreak - 1] = '\0';
140 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] got line: %s\n", __FILE__, __LINE__, line);
141 ED2KLink* ed2kLink = ED2KLink::parseED2KLink(line);
147 if (!ensureBufferCapacity(4)) {
150 uint32_t headerTagCount = 0;
151 growingBuffer.read(&headerTagCount, 4);
152 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] will read %d header tags.\n", __FILE__, __LINE__, headerTagCount);
153 for (uint32_t headerTagIndex = 0; headerTagIndex < headerTagCount; headerTagIndex++) {
155 if (!ensureBufferCapacity(1)) {
158 growingBuffer.read(&tagType, 1);
159 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag type %d.\n", __FILE__, __LINE__, tagType);
160 if (tagType == 0x02) {
161 StringTag* stringTag = readStringTag(true);
162 if (stringTag->getId() == 0x01) {
163 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] FT_FILENAME: “%s”\n", __FILE__, __LINE__, (char*) stringTag->getValue());
164 } else if (stringTag->getId() == 0x31) {
165 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] FT_COLLECTIONAUTHOR: “%s”\n", __FILE__, __LINE__, (char*) stringTag->getValue());
167 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] unknown string in header: “%s”\n", __FILE__, __LINE__, (char*) stringTag->getValue());
169 } else if (tagType == 0x07) {
170 BlobTag* blobTag = readBlobTag(true);
171 if (blobTag->getId() == 0x32) {
172 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] FT_COLLECTIONAUTHORKEY: %d bytes.\n", __FILE__, __LINE__, blobTag->getSize());
174 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] unknown block in header: %d bytes.\n", __FILE__, __LINE__, blobTag->getSize());
177 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] unknown tag type: %02x.\n", __FILE__, __LINE__, tagType);
180 fileCollectionCount = 0;
181 if (!ensureBufferCapacity(4)) {
184 growingBuffer.read(&fileCollectionCount, 4);
185 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] will read %d files.\n", __FILE__, __LINE__, fileCollectionCount);
186 collectionFileIndex = 0;
189 if (collectionFileIndex < fileCollectionCount) {
190 uint32_t fileTagCount = 0;
191 if (!ensureBufferCapacity(4)) {
194 growingBuffer.read(&fileTagCount, 4);
195 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] will read %d file tags.\n", __FILE__, __LINE__, fileTagCount);
196 StringTag* filenameTag = NULL;
198 HashTag* hashTag = NULL;
199 for (uint32_t fileTagIndex = 0; fileTagIndex < fileTagCount; fileTagIndex++) {
201 if (!ensureBufferCapacity(1)) {
204 growingBuffer.read(&tagType, 1);
206 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] reading tag type %d.\n", __FILE__, __LINE__, tagType);
207 if (tagType == 0x01) {
208 hashTag = readHashTag();
212 } else if (tagType == 0x02) {
213 StringTag* stringTag = readStringTag();
217 if (stringTag->getId() == 0x01) {
218 filenameTag = stringTag;
219 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read file name “%s”.\n", __FILE__, __LINE__, (char*) stringTag->getValue());
220 } else if (stringTag->getId() == 0xf6) {
221 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read file comment “%s”.\n", __FILE__, __LINE__, (char*) stringTag->getValue());
224 } else if ((tagType == 0x03) || (tagType == 0x08) || (tagType == 0x09) || (tagType == 0x0b)) {
225 if (!ensureBufferCapacity(1)) {
229 growingBuffer.read(&id, 1);
231 int neededBytes = (tagType == 0x03) ? 4 : ((tagType == 0x08) ? 2 : ((tagType == 0x09) ? 1 : 8));
232 if (!ensureBufferCapacity(neededBytes)) {
235 growingBuffer.read(&size, neededBytes);
236 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] file size is %llu bytes.\n", __FILE__, __LINE__, size);
237 } else if (id == 0xf7) {
238 uint8_t fileRating = 0;
239 if (!ensureBufferCapacity(1)) {
242 growingBuffer.read(&fileRating, 1);
243 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read file rating %d.\n", __FILE__, __LINE__, fileRating);
247 collectionFileIndex++;
249 if (filenameTag && hashTag) {
250 ED2KLink* ed2kLink = new ED2KLink((char*) filenameTag->getValue(), size, hashTag->getValue());
255 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] not enough data to decode file.\n", __FILE__, __LINE__);
264 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] reached end of collection.\n", __FILE__, __LINE__);
269 bool CollectionReader::ensureBufferCapacity(size_t byteCount) {
270 while (!readerInput->isEOF() && (growingBuffer.getRemaining() < byteCount)) {
271 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] only %d bytes remaning, need at least %d, reading more bytes.\n", __FILE__, __LINE__, growingBuffer.getRemaining(), byteCount);
274 if (readerInput->isEOF() && (growingBuffer.getRemaining() < byteCount)) {
275 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] need %d more bytes, but file is EOF.\n", __FILE__, __LINE__, (byteCount - growingBuffer.getRemaining()));
281 void CollectionReader::readMoreBytes() {
285 readBytes = readerInput->read(buffer, 1024);
286 growingBuffer.write(buffer, readBytes);
289 void CollectionReader::identifyCollectionType() {
292 readBytes = readerInput->read(&version, 4);
293 if ((readBytes < 4) || readerInput->isEOF()) {
296 if (version == 0x01) {
297 isTextCollection = false;
299 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] identified binary collection, version 1\n", __FILE__, __LINE__);
300 } else if (version == 0x02) {
301 isTextCollection = false;
303 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] identified binary collection, version 2\n", __FILE__, __LINE__);
304 } else if (!strncmp("ed2k", (char*) &version, 4)) {
305 isTextCollection = true;
306 growingBuffer.write(&version, 4);
308 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] identified text collection\n", __FILE__, __LINE__);
310 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] could not identify collection!\n", __FILE__, __LINE__);